You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
4.7 KiB

2 years ago
package class08;
/*
* char[][] matrixcharword
* word
*
* char[][] m = {
* { 'a', 'b', 'z' },
* { 'c', 'd', 'o' },
* { 'f', 'e', 'o' },
* };
* word = "zooe"
*
*
* 1
* word = "zoooz"z -> o -> o -> o -> z
*
* 2
* word = "zoooz"
*
* code
*
* */
public class Code03_FindWordInMatrix {
// 可以走重复的设定
public static boolean findWord1(char[][] m, String word) {
if (word == null || word.equals("")) {
return true;
}
if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) {
return false;
}
char[] w = word.toCharArray();
int N = m.length;
int M = m[0].length;
int len = w.length;
// dp[i][j][k]表示必须以m[i][j]这个字符结尾的情况下能不能找到w[0...k]这个前缀串
boolean[][][] dp = new boolean[N][M][len];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
dp[i][j][0] = m[i][j] == w[0];
}
}
for (int k = 1; k < len; k++) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
dp[i][j][k] = (m[i][j] == w[k] && checkPrevious(dp, i, j, k));
}
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (dp[i][j][len - 1]) {
return true;
}
}
}
return false;
}
// 可以走重复路
// 从m[i][j]这个字符出发能不能找到str[k...]这个后缀串
public static boolean canLoop(char[][] m, int i, int j, char[] str, int k) {
if (k == str.length) {
return true;
}
if (i == -1 || i == m.length || j == -1 || j == m[0].length || m[i][j] != str[k]) {
return false;
}
// 不越界m[i][j] == str[k] 对的上的!
// str[k+1....]
boolean ans = false;
if (canLoop(m, i + 1, j, str, k + 1) || canLoop(m, i - 1, j, str, k + 1) || canLoop(m, i, j + 1, str, k + 1)
|| canLoop(m, i, j - 1, str, k + 1)) {
ans = true;
}
return ans;
}
// 不能走重复路
// 从m[i][j]这个字符出发能不能找到str[k...]这个后缀串
public static boolean noLoop(char[][] m, int i, int j, char[] str, int k) {
if (k == str.length) {
return true;
}
if (i == -1 || i == m.length || j == -1 || j == m[0].length || m[i][j] != str[k]) {
return false;
}
// 不越界也不是回头路m[i][j] == str[k] 也对的上!
m[i][j] = 0;
boolean ans = false;
if (noLoop(m, i + 1, j, str, k + 1) || noLoop(m, i - 1, j, str, k + 1) || noLoop(m, i, j + 1, str, k + 1)
|| noLoop(m, i, j - 1, str, k + 1)) {
ans = true;
}
m[i][j] = str[k];
return ans;
}
public static boolean checkPrevious(boolean[][][] dp, int i, int j, int k) {
boolean up = i > 0 ? (dp[i - 1][j][k - 1]) : false;
boolean down = i < dp.length - 1 ? (dp[i + 1][j][k - 1]) : false;
boolean left = j > 0 ? (dp[i][j - 1][k - 1]) : false;
boolean right = j < dp[0].length - 1 ? (dp[i][j + 1][k - 1]) : false;
return up || down || left || right;
}
// 不可以走重复路的设定
public static boolean findWord2(char[][] m, String word) {
if (word == null || word.equals("")) {
return true;
}
if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) {
return false;
}
char[] w = word.toCharArray();
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[0].length; j++) {
if (process(m, i, j, w, 0)) {
return true;
}
}
}
return false;
}
// 从m[i][j]这个字符出发能不能找到w[k...]这个后缀串
public static boolean process(char[][] m, int i, int j, char[] str, int k) {
if (k == str.length) {
return true;
}
if (i == -1 || i == m.length || j == -1 || j == m[0].length || m[i][j] == 0 || m[i][j] != str[k]) {
return false;
}
m[i][j] = 0;
boolean ans = false;
if (process(m, i + 1, j, str, k + 1) || process(m, i - 1, j, str, k + 1) || process(m, i, j + 1, str, k + 1)
|| process(m, i, j - 1, str, k + 1)) {
ans = true;
}
m[i][j] = str[k];
return ans;
}
public static void main(String[] args) {
char[][] m = { { 'a', 'b', 'z' }, { 'c', 'd', 'o' }, { 'f', 'e', 'o' }, };
String word1 = "zoooz";
String word2 = "zoo";
// 可以走重复路的设定
System.out.println(findWord1(m, word1));
System.out.println(findWord1(m, word2));
// 不可以走重复路的设定
System.out.println(findWord2(m, word1));
System.out.println(findWord2(m, word2));
}
}