Algorithm 最长公共子序列,在所有三种可能情况下取最大值
我接近最长的公共子序列,如下所示:Algorithm 最长公共子序列,在所有三种可能情况下取最大值,algorithm,Algorithm,我接近最长的公共子序列,如下所示: LCS(m,n) = max( LCS(m-1,n), LCS(m,n-1), LCS(m-1,n-1) + (String1[m]==String2[n]) ); 然而,文本显示问题的逻辑如下: if( String1[m]==String2[n] ) LCS(m,n) = LCS(m-1,n-1) + 1; else LCS(m,n) = max( LCS(m-1,n), LCS(m,n-1) ); 我的方法会产生错误的结果吗?如果是,那么在什
LCS(m,n) = max( LCS(m-1,n), LCS(m,n-1), LCS(m-1,n-1) + (String1[m]==String2[n]) );
然而,文本显示问题的逻辑如下:
if( String1[m]==String2[n] )
LCS(m,n) = LCS(m-1,n-1) + 1;
else LCS(m,n) = max( LCS(m-1,n), LCS(m,n-1) );
我的方法会产生错误的结果吗?如果是,那么在什么样的情况下?如果它是正确的,你如何证明它的正确性
提前谢谢 我的(糟糕的)Java版本,它运行正常吗
//'main' method must be in a class 'Rextester'.
//Compiler version 1.8.0_111
import java.util.*;
import java.lang.*;
class Rextester
{
public static void main(String args[])
{
int[] a = {1,1,1,1,2,3,2,3};
int[] b = {1,1,1,1,3,4,3,4};
System.out.println(solve(a, b).toString());
System.out.println(solve2(a, b).toString());
}
private static void printL(int[][]len, int m, int n, int[] a, int[] b)
{
System.out.print(" a→ ");
for (int j = 0; j < m; ++j)
{
System.out.print(a[j]);
System.out.print(" ");
}
System.out.println();
for (int i = 0; i <= n; ++i)
{
if (i > 0) { System.out.print(" "); System.out.print(b[i-1]); System.out.print(" "); }
else { System.out.print("b↓ "); }
for (int j = 0; j <= m; ++j)
{
System.out.print(len[i][j]);
System.out.print(" ");
}
System.out.println();
}
}
private static List<Integer> solve(int[] a, int[] b)
{
int m = a.length;
int n = b.length;
System.out.println("Method 1");
int[][] len = new int[n+1][m+1];
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
len[i+1][j+1] = a[j] == b[i] ? 1 + len[i][j] : Math.max(len[i+1][j], len[i][j+1]);
printL(len, m, n, a, b);
List<Integer> c = new ArrayList<Integer>();
for (int i = n - 1, j = m - 1; len[i+1][j+1] > 0;)
{
if (a[j] == b[i]) { c.add(a[j]); i--; j--; }
else if (len[i+1][j] < len[i][j+1]) i--;
else j--;
}
Collections.reverse(c);
return c;
}
private static List<Integer> solve2(int[] a, int[] b)
{
int m = a.length;
int n = b.length;
System.out.println("Method 2");
int[][] len = new int[n+1][m+1];
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
len[i+1][j+1] = Math.max(Math.max(len[i+1][j], len[i][j+1]), (a[j] == b[i] ? 1 : 0) + len[i][j]);
printL(len, m, n, a, b);
List<Integer> c = new ArrayList<Integer>();
for (int i = n - 1, j = m - 1; len[i+1][j+1] > 0;)
{
if (a[j] == b[i]) { c.add(a[j]); i--; j--; }
else if (len[i+1][j] < len[i][j+1]) i--;
else j--;
}
Collections.reverse(c);
return c;
}
}
我的粗略证明:
如果您查看上表中的任何行LCS(m),您将看到它们都有递增的值,或者它们都是单调递增的。它们不能减少,因为LCS(m,n)表示长度为m的(sub)string1和长度为n的(sub)string2的最长公共子序列,如果n2>=n1,则LCS(m,n2)>=LCS(m,n1),因为如果n2>=n1,LCS(m,n2)包含LCS(m,n1)
对于LCS(n)列,使用相同的证明。现在有了LCS(m,n)LCS(m-1,n)),但后一种情况
(LCS(m-1,n-1)>LCS(m,n-1)
或LCS(m-1,n-1)>LCS(m-1,n))
从未发生过。所以你的方法是正确的。我认为它会奏效。画一张表并检查它。在表中的任何条目,我都找不到LCS(m-1,n-1)>LCS(m-1,n)或LCS(m-1,n-1)>LCS(m,n-1)的条目。不过我还在做一个可靠的证明…很好!另外,我们可以说abs(LCS(m,n-1)-LCS(m-1,n-1))
Method 1
a→ 1 1 1 1 2 3 2 3
b↓ 0 0 0 0 0 0 0 0 0
1 0 1 1 1 1 1 1 1 1
1 0 1 2 2 2 2 2 2 2
1 0 1 2 3 3 3 3 3 3
1 0 1 2 3 4 4 4 4 4
3 0 1 2 3 4 4 5 5 5
4 0 1 2 3 4 4 5 5 5
3 0 1 2 3 4 4 5 5 6
4 0 1 2 3 4 4 5 5 6
[1, 1, 1, 1, 3, 3]
Method 2
a→ 1 1 1 1 2 3 2 3
b↓ 0 0 0 0 0 0 0 0 0
1 0 1 1 1 1 1 1 1 1
1 0 1 2 2 2 2 2 2 2
1 0 1 2 3 3 3 3 3 3
1 0 1 2 3 4 4 4 4 4
3 0 1 2 3 4 4 5 5 5
4 0 1 2 3 4 4 5 5 5
3 0 1 2 3 4 4 5 5 6
4 0 1 2 3 4 4 5 5 6
[1, 1, 1, 1, 3, 3]