LCS修改版(Longest Common Subsequence 最长公共子序列)
题目描述
作为一名情报局特工,Nova君(2号)有着特殊的传达情报的技巧。为了避免被窃取情报,每次传达时,他都会发出两句旁人看来意义不明话,实际上暗号已经暗含其中。解密的方法很简单,分别从两句话里删掉任意多个字母,使得两句话剩余的部分相同,通过一定的删除手法,可以让剩余的部分相同且长度最大,就得到了可能的暗号。暗号可能有多个,还要进行筛选,现在情报局人手不够,希望你能助一臂之力,筛选工作不用你完成,你只需计算出暗号长度以及个数即可。(注意,字母的位置也是暗号的重要信息,位置不同的字母组成的暗号不算同一种,详见样例)
输入
多组测试数据(组数小于20)
每组数据输入两行,分别为两个字符串(只含英文字母,无空格),每个字符串以"." 结束
输出
对于每组数据,输出两行,第一行为暗号的长度,第二行为暗号的个数(答案可能很大,对个数100000000求模)
输入样例
AAAA.
AA.
输出样例
2 6
题目来源:http://biancheng.love/contest/17/problem/F/index
最长公共子序列的实现可参考:http://www.cnblogs.com/huangxincheng/archive/2012/11/11/2764625.html
和之前的不同在于需要计算出最长公共子序列一共有多少个!翻看不少博客很少有提到计算最长公共子序列的个数问题
下面给出代码实现:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int m=100000000;//对m求模 5 int f[2][5001]= {0},g[2][5001]= {0}; 6 7 int main() 8 { 9 string s1,s2; 10 while(cin>>s1>>s2) 11 { 12 memset(f,0,sizeof(f)); 13 memset(g,0,sizeof(g)); 14 int len1=s1.size()-1,len2=s2.size()-1;//串s1,s2长度 15 16 for(int i=0; i<=len2; i++) 17 g[0][i]=1; 18 int k; 19 for(int i=1; i<=len1; i++) 20 { 21 k=i & 1;//与运算 当i是奇数时k=1,当i时偶数是k是0 22 memset(g[k],0,sizeof(g[k])); 23 memset(f[k],0,sizeof(f[k])); 24 g[k][0]=1; 25 g[!k][0]=1; 26 for(int j=1; j<=len2; j++) 27 { 28 if(s1[i-1]==s2[j-1]) 29 { 30 f[k][j]=f[!k][j-1]+1; 31 g[k][j]=g[!k][j-1]; 32 g[k][j]%=m; 33 if(f[k][j]==f[!k][j]) 34 { 35 g[k][j]+=g[!k][j]; 36 g[k][j]%=m; 37 } 38 if(f[k][j-1]==f[k][j]) 39 { 40 g[k][j]+=g[k][j-1]; 41 g[k][j]%=m; 42 } 43 } 44 else 45 { 46 if(f[!k][j]>f[k][j-1]) 47 { 48 f[k][j]=f[!k][j]; 49 g[k][j]+=g[!k][j]; 50 g[k][j]%=m; 51 } 52 if(f[!k][j]<f[k][j-1]) 53 { 54 f[k][j]=f[k][j-1]; 55 g[k][j]+=g[k][j-1]; 56 g[k][j]%=m; 57 } 58 if(f[!k][j]==f[k][j-1]) 59 { 60 f[k][j]=f[!k][j]; 61 g[k][j]+=g[!k][j]+g[k][j-1]; 62 if(f[!k][j-1]==f[k][j])g[k][j]-=g[!k][j-1]; 63 g[k][j]=(g[k][j]+3*m)%m; 64 } 65 } 66 } 67 } 68 cout<<f[k][len2]<<endl; 69 cout<<g[k][len2]<<endl; 70 } 71 }
作者: 伊甸一点
出处: http://www.cnblogs.com/zpfbuaa/
本文版权归作者伊甸一点所有,欢迎转载和商用(须保留此段声明),且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
原文链接 如有问题, 可邮件(zpflyfe@163.com)咨询.