LCS--Longest Common Subsequence,即最长公共子序列,一般使用DP来解。
常规方法:
dp[i][j]表示字符串s1前i个字符组成的字符串与s2前j个字符组成的字符串的LCS的长度,则当s1[i-1]==s2[j-1]时,dp[i][j]=dp[i-1][j-1]+1,否则dp[i][j]=max(dp[i-1][j],dp[i][j-1])。
最终的dp[len1][len2]即最终答案。代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; char s1[],s2[];
int len1,len2;
int dp[][]; int main(){
while(~scanf("%s%s",s1,s2)){
len1=strlen(s1),len2=strlen(s2);
for(int i=;i<=len1;++i) dp[i][]=;
for(int i=;i<=len2;++i) dp[][i]=;
for(int i=;i<=len1;++i)
for(int j=;j<=len2;++j)
if(s1[i-]==s2[j-])
dp[i][j]=dp[i-][j-]+;
else
dp[i][j]=max(dp[i-][j],dp[i][j-]);
printf("%d\n",dp[len1][len2]);
}
return ;
}
如果需要打印路径:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; char s1[],s2[];
int len1,len2;
int dp[][],path[][]; void print(int p1,int p2){
if(p1==||p2==) return;
else{
if(path[p1][p2]==) print(p1-,p2-),printf("%c",s1[p1-]);
else if(path[p1][p2]==) print(p1-,p2);
else print(p1,p2-);
}
} int main(){
while(~scanf("%s%s",s1,s2)){
len1=strlen(s1),len2=strlen(s2);
for(int i=;i<=len1;++i) dp[i][]=;
for(int i=;i<=len2;++i) dp[][i]=;
for(int i=;i<=len1;++i)
for(int j=;j<=len2;++j)
if(s1[i-]==s2[j-])
dp[i][j]=dp[i-][j-]+,path[i][j]=;
else if(dp[i-][j]>=dp[i][j-])
dp[i][j]=dp[i-][j],path[i][j]=;
else
dp[i][j]=dp[i][j-],path[i][j]=;
printf("%d\n",dp[len1][len2]);
print(len1,len2);
printf("\n");
}
return ;
}
空间优化:
如果只需要求LCS的长度,实际上只需要dp[n]就行了,应用滚动数组。因为dp[i][j]由dp[i-1][j-1],dp[i-1][j],dp[i][j-1],用dp[j]表示dp[i][j],则更新dp[j]时用pre存储dp[i-1][j-1],此时的dp[j-1]表示dp[i][j-1],此时的dp[j]表示dp[i-1][j],这样就大大优化了空间,详见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; char s1[],s2[];
int len1,len2,pre,tmp;
int dp[]; int main(){
while(~scanf("%s%s",s1,s2)){
len1=strlen(s1),len2=strlen(s2);
memset(dp,,sizeof(dp));
for(int i=;i<=len1;++i){
pre=;
for(int j=;j<=len2;++j){
tmp=dp[j];
if(s1[i-]==s2[j-])
dp[j]=pre+;
else
dp[j]=max(dp[j-],dp[j]);
pre=tmp;
}
}
printf("%d\n",dp[len2]);
}
return ;
}
时间优化:
据说可以将LCS转换为LIS解法,从而使时间复杂度降为O(nlogn),但似乎在某些特殊情况复杂度比常规做法更麻烦,不被建议使用。等以后接触时再更......