我试图解决edit distance问题。我一直在使用的代码如下。
public static int minDistance(String word1, String word2) {
int len1 = word1.length();
int len2 = word2.length();
// len1+1, len2+1, because finally return dp[len1][len2]
int[][] dp = new int[len1 + 1][len2 + 1];
for (int i = 0; i <= len1; i++) {
dp[i][0] = i;
}
for (int j = 0; j <= len2; j++) {
dp[0][j] = j;
}
//iterate though, and check last char
for (int i = 0; i < len1; i++) {
char c1 = word1.charAt(i);
for (int j = 0; j < len2; j++) {
char c2 = word2.charAt(j);
//if last two chars equal
if (c1 == c2) {
//update dp value for +1 length
dp[i + 1][j + 1] = dp[i][j];
} else {
int replace = dp[i][j] + 1 ;
int insert = dp[i][j + 1] + 1 ;
int delete = dp[i + 1][j] + 1 ;
int min = replace > insert ? insert : replace;
min = delete > min ? min : delete;
dp[i + 1][j + 1] = min;
}
}
}
return dp[len1][len2];
}
这是一种DP方法。问题因为它使用了2D数组我们无法使用上述方法解决这个问题的大字符串。例如:字符串长度&gt; 100000。
那么无论如何都要修改这个算法来克服这个困难吗?
注意: 上面的代码将准确地解决小字符串的编辑距离问题。 (长度低于1000或接近)
正如您在代码中所看到的,它使用了Java 2D数组&#34; dp [] []&#34; 。因此,我们无法为大行和列初始化2D数组。
Ex:如果我需要检查2个长度超过100000的字符串
int[][] dp = new int[len1 + 1][len2 + 1];
以上将是
int[][] dp = new int[100000][100000];
因此它会产生stackOverflow错误。
所以上面的程序只适用于小长度的字符串。 我要问的是,有没有办法在java中有效地解决大字符串(长度> 100000)的这个问题。
答案 0 :(得分:2)
首先,在Java中分配100k x 100k int数组没有问题,你只需要在堆中进行,而不是在堆栈中(在具有大约80GB内存的机器上):)
其次,作为(非常直接的)提示:
请注意,在循环中,您一次只能使用2行 - 行i
和行i+1
。实际上,您从行i+1
计算行i
。获得i+1
后,您不再需要存储行i
。
这个巧妙的技巧允许您同时存储2行,从而将空间复杂度从n^2
降低到n
。既然你声明这是不是的家庭作业(即使你的个人资料属于CS本科...),我相信你会自己想出这些代码。
想到这一点我记得当我在CS学位上上课时遇到这个问题...