最长公共子序列(LCS)

注意最长公共子串(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;
       }
else dp[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++; else i++; } } return ans; } int main() { while(cin>>s[0]>>s[1]) { cout<<solve()<<endl; } return 0; }

 

posted @ 2016-11-04 12:48  Luke_Ye  阅读(298)  评论(0编辑  收藏  举报