首先我贴个简单的模板,用dfs来解决的
int LCS(int i,int j)
{
if(i>=lena || j>=lenb)
return 0;
if(a[i]==b[j])
return 1+LCS(i+1,j+1);
else
return LCS(i+1,j)>LCS(i,j+1)? LCS(i+1,j):LCS(i,j+1);
} //用的时候是LCS(0,0)
有时候我们需要把公共子序列求出
void LCS()
{
int i,j;
for(i=1;i<=strlen(a);i++)
{
for(j=1;j<=strlen(b);j++)
{
if(a[i-1]==b[j-1]) ///注意这里的下标是i-1与j-1
{
num[i][j]=num[i-1][j-1]+1;
flag[i][j]=1; ///斜向下标记
}
else if(num[i][j-1]>num[i-1][j])
{
num[i][j]=num[i][j-1];
flag[i][j]=2; ///向右标记
}
else
{
num[i][j]=num[i-1][j];
flag[i][j]=3; ///向下标记
}
}
}
}
void getLCS()
{
char res[500];
int i=strlen(a);
int j=strlen(b);
int k=0; ///用于保存结果的数组标志位
while(i>0 && j>0)
{
if(flag[i][j]==1) ///如果是斜向下标记
{
res[k]=a[i-1];
k++;
i--;
j--;
}
else if(flag[i][j]==2) ///如果是斜向右标记
j--;
else if(flag[i][j]==3) ///如果是斜向下标记
i--;
}
for(i=k-1;i>=0;i--)
printf("%c",res[i]);
}
下面是最长公共子序列nlogn算法,有可能退化,转自bin314 的BLOG
最长公共子序列问题:
给定2个字符串,求其最长公共子串。如abcde和dbada的最长公共字串为bd。
动态规划:dp[i][j]表示A串前i个和B串前j个的最长公共子串的长度。
则
若A[i] == B[j] , dp[i][j] = dp[i-1][j-1] + 1;
否则 dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
时间复杂度O(N*M)。
dp[i][j]仅在A[i]==B[j]处才增加,对于不相等的地方对最终值是没有影响的。
故枚举相等点处可以对其进行优化。
则对于dp[i][j](这里只计算A[i]==B[j]的i和j),取最大的dp[p][q],满足(p
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 1501 ;
vector<int> location[26] ;
int c[maxn*maxn] , d[maxn*maxn] ;
inline int get_max(int a,int b) { return a > b ? a : b ; }
//nlogn 求lcs
int lcs(char a[],char b[])
{
int i , j , k , w , ans , l , r , mid ;
for( i = 0 ; i < 26 ; i++) location[i].clear() ;
for( i = strlen(b)-1 ; i >= 0 ; i--) location[b[i]-'a'].push_back(i) ;
for( i = k = 0 ; a[i] ; i++)
{
for( j = 0 ; j < location[w=a[i]-'a'].size() ; j++,k++) c[k] = location[w][j] ;
}
d[1] = c[0] ; d[0] = -1 ;
for( i = ans = 1 ; i < k ; i++)
{
l = 0 ; r = ans ;
while( l <= r )
{
mid = ( l + r ) >> 1 ;
if( d[mid] >= c[i] ) r = mid - 1 ;
else l = mid + 1 ;
}
if( r == ans ) ans++,d[r+1] = c[i] ;
else if( d[r+1] > c[i] ) d[r+1] = c[i] ;
}
return ans ;
}
int main()
{
char a[maxn] , b[maxn] ;
while (~scanf("%s%s",a,b))
{
printf("%d\n",lcs(a,b));
}
}