C++公共子序列

xiaoxiao2021-02-28  101

1808:公共子序列

总时间限制: 1000ms 内存限制: 65536kB 描述 我们称序列Z = < z1, z2, …, zk >是序列X = < x1, x2, …, xm >的子序列当且仅当存在 严格上升 的序列< i1, i2, …, ik >,使得对j = 1, 2, … ,k, 有xij = zj。比如Z = < a, b, f, c > 是X = < a, b, c, f, b, c >的子序列。

现在给出两个序列X和Y,你的任务是找到X和Y的最大公共子序列,也就是说要找到一个最长的序列Z,使得Z既是X的子序列也是Y的子序列。

输入

输入包括多组测试数据。每组数据包括一行,给出两个长度不超过200的字符串,表示两个序列。两个字符串之间由若干个空格隔开。

输出

对每组输入数据,输出一行,给出两个序列的最大公共子序列的长度。 样例输入

abcfbc abfcab programming contest abcd mnp

样例输出

4 2 0

来源 翻译自Southeastern Europe 2003的试题

方案一:

记忆化递归 状态: Accepted

#include<iostream> #include<cstring> using namespace std; string a,b; int la,lb,A[201][201]; int dfs(int i,int j) { if(A[i][j]+1) return A[i][j]; if(i==0&&j==0) { if(a[i]==b[j]) return A[i][j]=1; else return A[i][j]=0; } if(i==0) { for(int k=j;k>=0;k--) if(a[i]==b[k]) return A[i][j]=1; return A[i][j]=0; } if(j==0) { for(int k=i;k>=0;k--) if(a[k]==b[j]) return A[i][j]=1; return A[i][j]=0; } if(a[i]==b[j]) return A[i][j]=1+dfs(i-1,j-1); else return A[i][j]=max(dfs(i,j-1),dfs(i-1,j)); } int main() { while(cin>>a>>b) { memset(A,-1,sizeof(A)); cout<<dfs(a.length()-1,b.length()-1)<<endl; } }

方案二:

动态规划 状态: Accepted

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int num=0; char a[1010],b[1010]; int dp[1010][1010],mark[1010][1010],lena,lenb; void lcs() { int i,j; memset(dp,0,sizeof(dp)); for(i=1;i<=lena;++i) mark[i][0]=1; //重置,用于标记 for(i=1;i<=lenb;++i) mark[0][i]=-1; //重置 for(i=1;i<=lena;++i) { for(j=1;j<=lenb;++j) { if(a[i-1]==b[j-1]) //如果有子串相同 { dp[i][j]=dp[i-1][j-1]+1; //长度加一 mark[i][j]=0;//标记 } else if(dp[i-1][j]>=dp[i][j-1]) { dp[i][j]=dp[i-1][j]; //取最大的 mark[i][j]=1; } else { dp[i][j]=dp[i][j-1]; mark[i][j]=-1; } } } } void output(int x,int y) { if(!x&&!y) //都为0 return ; if(mark[x][y]==0) { output(x-1,y-1); num++; } else if(mark[x][y]==1) output(x-1,y); else output(x,y-1); } int main() { while(scanf("%s%s",a,b)!=EOF) { num=0; lena=strlen(a); lenb=strlen(b); lcs(); output(lena,lenb); printf("%d\n",num); } return 0; }

方案三:

深搜 状态: Time Limit Exceeded

#include<iostream> #include<cstring> using namespace std; string x,y; int lenx,leny,maxn; void dfs(int s,int t,int g) { if(t>=lenx||g>=leny) return ; for(int i=t;i<lenx;i++) { int j; for(j=g;j<leny;j++) if(x[i]==y[j]) break; if(j==leny) continue; dfs(s+1,i+1,j+1); if(s>maxn) maxn=s; } } int main() { while(cin>>x>>y) { maxn=0; lenx=x.length(); leny=y.length(); dfs(1,0,0); cout<<maxn<<endl; } }
转载请注明原文地址: https://www.6miu.com/read-32174.html

最新回复(0)