LCS (Longest Common Subsequence)(连续+不连续两种情况)
关于最长公共子序列:
LCS是两个序列相似性的一种度量方法;
若序列s1:2,5,7,9,3,1,2
s2:3,5,3,2,8
则LCS为:5,3,2
思路可参考:http://www.csie.ntnu.edu.tw/~u91029/LongestCommonSubsequence.html
具体代码实现为:
1 #include<iostream> 2 using namespace std; 3 4 int s1[7+1]={0,2,5,7,9,3,1,2}; 5 int s2[7+1]={0,3,5,3,2,8}; 6 const int s1_length=8; 7 const int s2_length=6; 8 const int LEFT=1; 9 const int UP=2; 10 const int UP_LEFT=3; 11 const int LEFTORUP=4; 12 13 int arr[7+1][5+1]={0}; 14 int pre[7+1][5+1]={0}; 15 16 void LCS(); 17 void print_LCS(int i,int j); 18 19 int main() 20 { 21 cout<<"the LCS of the sequence is:"; 22 LCS(); 23 return 0; 24 } 25 26 void LCS() 27 { 28 for(int i=0;i<s2_length;++i) 29 arr[0][i]=0; 30 for(int i=0;i<s1_length;++i) 31 arr[i][0]=0; 32 33 for(int i=1;i<s1_length;++i) 34 for(int j=1;j<s2_length;++j) 35 if(s1[i]==s2[j]) 36 { 37 arr[i][j]=arr[i-1][j-1]+1; 38 pre[i][j]=UP_LEFT; 39 } 40 else 41 { 42 if(arr[i-1][j]==arr[i][j-1]) 43 { 44 arr[i][j]=arr[i-1][j]; 45 pre[i][j]=LEFTORUP; 46 } 47 else if(arr[i-1][j]>arr[i][j-1]) 48 { 49 arr[i][j]=arr[i-1][j]; 50 pre[i][j]=UP; 51 } 52 else 53 { 54 arr[i][j]=arr[i][j-1]; 55 pre[i][j]=LEFT; 56 } 57 } 58 59 print_LCS(s1_length-1,s2_length-1); 60 } 61 62 void print_LCS(int i,int j) 63 { 64 if(i==0||j==0) 65 return; 66 67 if(pre[i][j]==UP_LEFT) 68 { 69 cout<<s1[i]<<'\t'; 70 print_LCS(i-1,j-1); 71 } 72 else if(pre[i][j]==UP) 73 print_LCS(i-1,j); 74 else if(pre[i][j]==LEFT) 75 print_LCS(i,j-1); 76 }
以上情况中两个序列只存在一个LCS,但是若存在多个LCS应该怎么解决呢?
若序列s1:2,5,7,9,3,1,2
s2:3,5,3,2,8,7,9
则LCS为:5,3,2; 2,7,9; 5,7,9

以上两个表格为算法的思路,上面表格为顺序思路,arr[i][j]表示s1(1:i) s2(1:j)两个序列的LCS长度,下面表格为回溯思路,从右下角开始根据方向得到LCS,其中数字意义为:
LEFT=1;
UP=2;
UP_LEFT=3;
LEFTORUP=4;顺序时由上面或左面数字得到(区别于只有一个LCS存在),目的在于回溯时可以得到序列所有的LCS,代码还没有实现。
关于最长字串:
若序列s1:2,5,3,2,7,91,
s2:3,5,3,2,8
则最长字串:5,3,2
算法:lcs(i,j) = lcs(i-1,j-1) + 1,otherwise:lcs(i,j) = 0 ,相比于不连续情况:
LCS(s1, s2) ={ LCS(sub1, s2) or LCS (s1, sub2) or LCS(sub1, sub2) , when e1 != e2 // LCS(sub1, sub2) + e1, when e1 == e2}
具体代码:
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 using namespace std; 5 6 int stringLCS(string str1,string str2) 7 { 8 int len1=str1.size(); 9 int len2=str2.size(); 10 11 vector<vector<int> >arr(len1); 12 for(int i=0;i<len1;++i) 13 arr[i].resize(len2); 14 for(int i=0;i<len1;++i) 15 for(int j=0;j<len2;++j) 16 arr[i][j]=0; 17 18 //(inx,iny):最长字串最后一个字符坐标 19 int inx=-1; 20 int iny=-1; 21 //初始化字串长度 22 int maxLength=0; 23 for(int i=0;i<len1;++i) 24 for(int j=0;j<len2;++j) 25 { 26 if(str1[i]==str2[j]) 27 { 28 if(i==0||j==0) 29 { 30 arr[i][j]=1; 31 //更新字串长度及坐标 32 if(arr[i][j]>maxLength) 33 { 34 inx=i; 35 iny=j; 36 maxLength=arr[i][j]; 37 } 38 } 39 else 40 { 41 if(arr[i-1][j-1]!=0) 42 arr[i][j]=arr[i-1][j-1]+1; 43 else 44 arr[i][j]=1; 45 46 if(arr[i][j]>maxLength) 47 { 48 inx=i; 49 iny=j; 50 maxLength=arr[i][j]; 51 } 52 } 53 } 54 } 55 56 //输出相同字串 57 for(int i=inx,j=iny;i>=0&&j>=0;--i,--j) 58 { 59 if(arr[i][j]==0) 60 break; 61 else 62 cout<<str1[i]<<ends; 63 } 64 cout<<endl; 65 66 return maxLength; 67 } 68 69 int main() 70 { 71 string str1="helloworld"; 72 string str2="oword"; 73 74 cout<<stringLCS(str1,str2)<<endl; 75 return 0; 76 }

浙公网安备 33010602011771号