您的位置:首页 > 其它

最长公共子序列问题模板(不要求连续)

2016-08-02 15:36 267 查看
首先我贴个简单的模板,用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));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐