---
# System prepended metadata

title: 79. Word Search
tags: [C++, LeetCode-Medium]

---

# 79. Word Search
Difficulty: Medium

## Solution

```cpp=
/**
*** Author: R-CO
*** E-mail: daniel1820kobe@gmail.com
*** Date: 2020-08-28
**/
#include <cstdlib>
#include <iostream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

#define VERSION_1 0
#define VERSION_2 0
#define VERSION_3 1

struct TestCaseStruct {
  struct Input {
    vector<vector<char>> board;
    string word;
  } input;
  bool expected_output;
};

#if VERSION_1
struct Position {
  Position(int i, int j) {
    this->i = i;
    this->j = j;
    this->next_direction = 0;
  }

  Position(int i, int j, int next_direction) {
    this->i = i;
    this->j = j;
    this->next_direction = next_direction;
  }
  int i;
  int j;
  int next_direction;
};

// non-recursive, but with BUG
class Solution {
 public:
  bool exist(vector<vector<char>>& board, string word) {
    vector<vector<int>> used(board.size(), vector<int>(board[0].size(), 0));
    for (int i = 0; i < board.size(); ++i) {
      for (int j = 0; j < board[i].size(); ++j) {
        size_t index = 0;
        if (board[i][j] == word[index++]) {
          used[i][j] = 1;
          stack<Position> s;
          s.emplace(Position(i, j, -1));
          while (index < word.size()) {
            auto current_index = index;
            auto& current_position = s.top();
            ++current_position.next_direction;
            Position adjecent[] = {
                {current_position.i - 1, current_position.j},
                {current_position.i, current_position.j + 1},
                {current_position.i + 1, current_position.j},
                {current_position.i, current_position.j - 1}};
            for (int next_direction = current_position.next_direction;
                 next_direction < 4; ++next_direction) {
              const auto& next = adjecent[next_direction];
              if (next.i < 0 || next.i >= board.size() || next.j < 0 ||
                  next.j >= board[i].size()) {
                continue;
              }
              if (used[next.i][next.j] == 1 ||
                  board[next.i][next.j] != word[index]) {
                continue;
              }
              used[next.i][next.j] = 1;
              s.emplace(Position(next.i, next.j, -1));
              ++index;
              break;
            }
            if (index == current_index) {
              used[current_position.i][current_position.j] = 0;
              --index;
              s.pop();
              if (s.empty()) {
                break;  // break "while (index < word.size())"
              }
            }
          }
          if (index == word.size()) {
            return true;
          }
          used[i][j] = 0;
        }
      }
    }
    return false;
  }
};
#endif

#if VERSION_2
struct Point {
  Point(int i, int j) {
    this->i = i;
    this->j = j;
  }

  int i;
  int j;
};

class Solution {
 public:
  bool exist(vector<vector<char>>& board, string word) {
    // board is m*n
    m_ = board.size();
    n_ = board[0].size();

    word_size_ = word.size();

    Point current_point(0, 0);
    for (current_point.i = 0; current_point.i < m_; ++current_point.i) {
      for (current_point.j = 0; current_point.j < n_; ++current_point.j) {
        size_t word_index = 0;
        if (board[current_point.i][current_point.j] == word[word_index]) {
          if (FindRecursively(board, word, current_point, word_index)) {
            return true;
          }
        }
      }
    }

    return false;
  }

 private:
  bool FindRecursively(vector<vector<char>>& board, const string& word,
                       Point current_point, size_t word_index) {
    if (++word_index >= word_size_) {
      return true;
    }

    char current_point_symbol = board[current_point.i][current_point.j];
    board[current_point.i][current_point.j] = '\0';
    vector<Point> adjecent_points = {{current_point.i - 1, current_point.j},
                                     {current_point.i, current_point.j + 1},
                                     {current_point.i + 1, current_point.j},
                                     {current_point.i, current_point.j - 1}};
    for (const auto& point : adjecent_points) {
      /*if (point.i < 0 || point.i >= m_ || point.j < 0 || point.j >= n_) {
        continue;
      }
      if (board[point.i][point.j] == '\0' ||
          board[point.i][point.j] != word[word_index]) {
        continue;
      }
      if (FindRecursively(board, word, point, word_index)) {
        return true;
      }*/
      if ((point.i >= 0 && point.i < m_ && point.j >= 0 && point.j < n_) &&
          board[point.i][point.j] != '\0' &&
          board[point.i][point.j] == word[word_index]) {
        if (FindRecursively(board, word, point, word_index)) {
          board[current_point.i][current_point.j] = current_point_symbol;
          return true;
        }
      }
    }

    board[current_point.i][current_point.j] = current_point_symbol;
    return false;
  }

  // board is m*n
  size_t m_;
  size_t n_;
  size_t word_size_;
};
#endif

#if VERSION_3
struct Point {
  Point(int i, int j) {
    this->i = i;
    this->j = j;
  }

  int i;
  int j;
};

class Solution {
 public:
  bool exist(vector<vector<char>>& board, string word) {
    // board is m*n
    m_ = board.size();
    n_ = board[0].size();

    Point current_point(0, 0);
    for (current_point.i = 0; current_point.i < m_; ++current_point.i) {
      for (current_point.j = 0; current_point.j < n_; ++current_point.j) {
        const char* w = word.c_str();
        if (board[current_point.i][current_point.j] == *w) {
          if (FindRecursively(board, w, current_point)) {
            return true;
          }
        }
      }
    }

    return false;
  }

 private:
  bool FindRecursively(vector<vector<char>>& board, const char* w,
                       const Point& current_point) {
    if (*(++w) == '\0') {
      return true;
    }

    char current_point_symbol = board[current_point.i][current_point.j];
    board[current_point.i][current_point.j] = '\0';
    vector<Point> adjecent_points{{current_point.i - 1, current_point.j},
                                  {current_point.i, current_point.j + 1},
                                  {current_point.i + 1, current_point.j},
                                  {current_point.i, current_point.j - 1}};
    for (const auto& point : adjecent_points) {
      if ((point.i >= 0 && point.i < m_ && point.j >= 0 && point.j < n_) &&
          board[point.i][point.j] != '\0' && board[point.i][point.j] == *w) {
        if (FindRecursively(board, w, point)) {
          board[current_point.i][current_point.j] = current_point_symbol;
          return true;
        }
      }
    }

    board[current_point.i][current_point.j] = current_point_symbol;
    return false;
  }

  // board is m*n
  size_t m_;
  size_t n_;
};
#endif

int main(int argc, char* argv[]) {
  /*
    board =
    [
      ['A','B','C','E'],
      ['S','F','C','S'],
      ['A','D','E','E']
    ]
    Given word = "ABCCED", return true.
    Given word = "SEE", return true.
    Given word = "ABCB", return false.

    board2 =
    [
      ['a', 'b'],
      ['c', 'd']
    ]
    Given word = "dbac", return true.

    [["b","a","a","b","a","b"],
		 ["a","b","a","a","a","a"],
		 ["a","b","a","a","a","b"],
		 ["a","b","a","b","b","a"],
		 ["a","a","b","b","a","b"],
		 ["a","a","b","b","b","a"],
		 ["a","a","b","a","a","b"]
		]
    "ababaababaaabbabbaabbaabbaba", return true.
  */
  const vector<vector<char>> board = {
      {'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}};
  const vector<vector<char>> board2 = {{'a', 'b'}, {'c', 'd'}};
  const vector<vector<char>> board3 = {
      {'b', 'a', 'a', 'b', 'a', 'b'}, {'a', 'b', 'a', 'a', 'a', 'a'},
      {'a', 'b', 'a', 'a', 'a', 'b'}, {'a', 'b', 'a', 'b', 'b', 'a'},
      {'a', 'a', 'b', 'b', 'a', 'b'}, {'a', 'a', 'b', 'b', 'b', 'a'},
      {'a', 'a', 'b', 'a', 'a', 'b'}};
  TestCaseStruct test_cases[] = {
      {{board, "ABCCED"}, true},
      {{board, "SEE"}, true},
      {{board, "ABCB"}, false},
      {{board2, "dbac"}, true},
      {{board3, "ababaababaaabbabbaabbaabbaba"}, true}};

  Solution solution;
  for (auto& test_case : test_cases) {
    if (solution.exist(test_case.input.board, test_case.input.word) ==
        test_case.expected_output) {
      cout << "test case = [" << test_case.input.word
           << "] is pass." << std::endl;
    } else {
      cout << "test case = [" << test_case.input.word
           << "] is fail." << std::endl;
    }
  }

  return EXIT_SUCCESS;
}


```

## Result

Success
Details 
Runtime: 100 ms, faster than 58.07% of C++ online submissions for Word Search.
Memory Usage: 19.3 MB, less than 53.49% of C++ online submissions for Word Search.

###### tags: `LeetCode-Medium` `C++`
