注意最长公共子串(Longest CommonSubstring)和最长公共子序列(LongestCommon Subsequence, LCS)的区别:子串(Substring)是串的一个连续的部分,子序列(Subsequence)则是从不改变序列的顺序,而从序列中去掉任意的元素而获得的新序列;更简略地说,前者(子串)的字符的位置必须连续,后者(子序列LCS)则不必。比如字符串acdfg同akdfc的最长公共子串为df,而他们的最长公共子序列是adf。LCS可以使用动态规划法解决。
学习了http://blog.csdn.net/v_july_v/article/details/6695482的思想,写了O(mn)的算法
#include <iostream> #include <algorithm> #include <string> #include <cstdio> #define N 105 using namespace std; int dp[N][N]; string s[2]; int s1,s2; int Max(int a,int b) {return a>b?a:b; } bool same(int i,int j) {if(s[0][i]==s[1][j])return true;return false; } //如果需要输出基于最长公共字串的两串合并,参考hdu1503的AC代码 string solve()//输出最长公共字串 {s1=-1,s2=-1;for(int i=0; i<N; i++) for(int j=0; j<N; j++) dp[i][j]=0;for(int i=s[0].length()-1; i>=0; i--)//自上而下遍历,方便还原的时候顺序还原for(int j=s[1].length()-1; j>=0; j--){if(same(i,j)){dp[i][j]=dp[i+1][j+1]+1;if(s1==-1) s1=i;s2=j;
}elsedp[i][j]=Max(dp[i+1][j],dp[i][j+1]);}string ans="";int i=0,j=0;while(i<s[0].length()&&j<s[1].length()){if(same(i,j))ans+=s[0][i],i++,j++;else{if(dp[i][j+1]>dp[i+1][j])j++;elsei++;}}return ans; } int main() {while(cin>>s[0]>>s[1]){cout<<solve()<<endl;}return 0; }