问题
Given a matrix of characters and a string, find whether the string can be obtained from the matrix. From each character in the matrix, we can move up/down/right/left. For example, if the matrix[3][4] is:
o f a s
l l q w
z o w k
and the string is follow
, then the function should return true.
The only approach I can think of is a backtracking algorithm that searches whether the word is possible or not. Is there any other faster algorithm to approach this problem?
And suppose I have a lot of queries (on finding whether a word exists or not). Then can there be some preprocessing done to answer the queries faster?
回答1:
You can solve this using DFS. Let's define a graph for the problem. The vertices of the graph will comprise of the cell of a combination of cell of the matrix and a length of prefix of the string we are searching for. When we are at a given vertex this will mean that all the characters of the specified prefix were matched so far and that we currently are at the given cell.
We define edges as connecting cells adjacent by a side and doing a "valid" transaction. That is the cell we are going to should be the next in the string we are searching for.
To solve the problem we do a DFS from all cells that contain the first letter of the string and prefix length 1(meaning we've matched this first letter). From there on we continue the search and on each step we compute which are the edges going out of the current position(cell/string prefix length combination). We terminate the first time we reach a prefix of length L
- the length of the string.
Note that DFS may be considered backtracking but what is more important is to keep track of the nodes in the graph we've already visited. Thus the overall complexity is bound by N * M * L
where N
and M
are the dimensions of the matrix and L
- the length of the string.
回答2:
You could of course find all possible strings (start with a charater and go as far as you can). This can be done with a recursive function.
grid:
abc
def
ghi
strings:
abcfedghi
abcfehgd
abcfehi
abedghif
abefc
abefighd
abehgd
abehifc
ad...
...
Then sort these strings and when looking for a word use a binary search on the list. (When looking for an n letter word you would of course only consider the first n letters of the strings in the list.) A lot of preparation and much memory needed, but searching will be fast. So if you use the same grid again and again, the preparation may finally pay :-)
回答3:
Below is the pseudo code for finding if the given string is present in a given matrix. Here visited keeps track of the location of the string in the matrix and it uses backtracking for keeping track of that. I hope this is helpful.
bool isSafe(matrix[n][m], int visited[n][m], int i, int j, int n, int m){
if(i<m && j<n && i>=0 && j>=0 && visited[i][j] == 0)
return true;
return false;
}
bool dfs(char matrix[n][m], int i, int j, int visited[n][m], char str[], int index){
if(index == strlen(str))
return true;
// row moves
int x[] = {-1, 0, 1, -1};
// col moves
int y[] = {0, -1, 1, 0};
if(str[index] == matrix[i][j]){
visited[i][j] = 1;
// for all the neighbours
for(int k = 0; k<4; k++){
// mark given position visited
next_x = i + x[k];
next_y = j + y[k];
if(isSafe(matrix, visited, next_x, next_y, n, m)){
if(dfs(matrix, next_x, next_y, visited, str, index+1) == true)
return true;
}
}
// backtrack
visited[i][j] = 0;
}
return false;
}
bool isPresent(char matrix[n][m], char str[]){
// visited initialized to 0
int visited[n][m] = {0};
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
if(dfs(matrix, i, j, n, m ,visited, str, 0) == true)
return true;
}
return false;
}
来源:https://stackoverflow.com/questions/24006249/find-if-a-string-can-be-obtained-from-a-matrix-of-characters