C++实现最长公共子序列和最长公共子串
可能直接看上面的公式不是很能理解,下面这段话,应该很直白的解释了上面的公式,可以对比着理解下:
Xi = <x1,x2,x3,....xi> 即X序列的前i个字符(1<= i <= m)(前缀)
Yj = <y1,y2,y3,....yi> 即Y序列的前j个字符(1<= j <= m)(前缀)
假定Z = <z1,z2,z3,...zk>
是LCS(X,Y)中的一个。
·若xm = yn(最后一个字符相同),则不难用反正法证明:该字符必是X与Y的任一最长公共子序列Z(设长度为k)的最后一个字符,即有zk = xm = yn,且显然有Zk-1∈LCS(Xm-1,Yn-1),即Z的前缀Zk-1是Xm-1与Yn-1的最长公共子序列。此时,问题化归成求Xm-1与Yn-1的LCS(LCS(X,Y))的长度等于LCS(Xm-1,Yn-1)的长度加1)。
·若xm≠yn,则亦不难用反证法证明:要么Z∈LCS(Xm-1, Y),要么Z∈LCS(X , Yn-1)。由于zk≠xm与zk≠yn其中至少有一个必成立,若zk≠xm则有Z∈LCS(Xm-1 , Y);类似的,若zk≠yn 则有Z∈LCS(X , Yn-1)。此时,问题化归成求Xm-1与Y的LCS及X与Yn-1的LCS。LCS(X , Y)的长度为:max{LCS(Xm-1 , Y)的长度, LCS(X , Yn-1)的长度}。
版本一:这个版本对lcs的打印比较晦涩难懂,但是只要理解还是可以看懂。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int lcs( string &str1,string &str2,vector< vector<int> >& c )
{
const int len1 = str1.length();
const int len2 = str2.length();
for( int i=0;i<=len1;++i )
{
for( int j=0;j<=len2;++j )
{
if( !i || !j ){
c[i][j] = 0;
continue;
}
if( str1[i-1] == str2[j-1] )
{
c[i][j] = c[i-1][j-1] + 1;