问题 G: 最长公共子串问题
希腊有一个著名的历史学家,他为了专心写一本史学巨著,而把自己关在一个高塔之上。有一天,他目睹了一场凶杀案的发生,但事后,他惊讶地发现所有围观人的证词都不一样,甚至有的完全相反。于是,他放弃了继续写作的念头。他说:“人们连发生在眼前的事实都分辨不清,我又怎么知道我写的历史是真是假呢?”
虽然历史的真假我们很难辨别,但文章是否抄袭,我们还是可以用所谓的LCS算法解决的。
给出两个字符串S1和S2,我们现在希望了解两个字符串之间的“相似度”。这个相似度是这样定义的:找出第三个字符串S3,组成S3的元素也出现在S1和S2中,而且这些元素必须是以相同的顺序出现,但不必要是连续的。能找到的S3越长则S1和S2就越相似。相似度即是这个S3的长度。例如,当S1="abcde",S2="dabfda",S3就是"abd", S1和S2的相似度就是3。
输入
第一行为一个整数,表示第一个字符串的长度。
第二行为第一个字符串。
第三行为一个整数,表示第二个字符串的长度。
第二行为第二个字符串。
输出
一个整数,即两个字符串的相似度。
样例输入 Copy
5
abccb
5
acabc
样例输出 Copy
3
#include<cstdio> #include<iostream> #include<algorithm> #include<map> #include<bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int INF=0x3f3f3f3f; const int maxn=5e3; int n,m; string str1,str2; int dp[maxn][maxn]; void inint(){ cin>>n; cin>>str1; cin>>m; cin>>str2; } int main(){ inint(); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(str1[i-1]==str2[j-1]){ dp[i][j]=dp[i-1][j-1]+1; } else{ dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } } printf("%d",dp[n][m]); }
输出方案:
#include<cstdio> #include<iostream> #include<algorithm> #include<map> #include<bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int INF=0x3f3f3f3f; const int maxn=5e3; int n,m; string str1,str2; int dp[maxn][maxn]; char ans[maxn]; void inint(){ cin>>n; cin>>str1; cin>>m; cin>>str2; } int main(){ inint(); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(str1[i-1]==str2[j-1]){ dp[i][j]=dp[i-1][j-1]+1; } else{ dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cout<<dp[i][j]<<" "; } cout<<endl; } int l=n,r=m; int p=0; while(l>0&&r>0){ if(str1[l-1]==str2[r-1]){ ans[p++]=str1[l-1]; l--; r--; } else if(dp[l][r-1]>dp[l-1][r]){ r--; } else{ l--; } } cout<<endl; printf("%d\n",dp[n][m]); for(int i=p-1;i>=0;i--){ cout<<ans[i]; } }
#include<cstdio> #include<iostream> #include<algorithm> #include<map> #include<bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int INF=0x3f3f3f3f; const int maxn=5e3; int n,m; string str1,str2; int dp[maxn][maxn]; char ans[maxn]; void inint(){ cin>>n; cin>>str1; cin>>m; cin>>str2; } int main(){ inint(); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(str1[i-1]==str2[j-1]){ dp[i][j]=dp[i-1][j-1]+1; } else{ dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cout<<dp[i][j]<<" "; } cout<<endl; } int l=n,r=m; int p=0; while(l>0&&r>0){ if(str1[l-1]==str2[r-1]){ ans[p++]=str1[l-1]; l--; r--; } else if(dp[l][r-1]>dp[l-1][r]){ r--; } else{ l--; } } cout<<endl; printf("%d\n",dp[n][m]); for(int i=p-1;i>=0;i--){ cout<<ans[i]; } }