输出最长公共子序列

试题描述

    还是公共子序列,如果不知道什么叫公共子序列,请先阅读第0071题。本题给定两个字符串 str1 和 str2 ,请编写程序求出这两个字符串最长的公共子串。如果最大长度的公共子串有多个,输出字典序最小的那一个。

输入
两行,每行一个只含英文字母的字符串
输出
一个字符串
输入示例
ABCDDDBAMN BCDABM
输出示例
BCDAM
其他说明
输入的字符串长度均不会超过1000。

 

#include<cstdio>
#include<cctype>
#include<algorithm>
#include<cstring>
#define maxn 1005
using namespace std;
inline int read()
{
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-')f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
int lasta[maxn][27],lastb[maxn][27]; 
int f[maxn][maxn],ans[maxn],cnt;
char a[maxn],b[maxn];
bool flag;
void dfs(int res,int n,int m)
{
 if(flag) return;
 if(res==0)
    {
 flag=1;
 for(int i=0;i<cnt;i++)
 printf("%c",ans[i]+'A');
 printf("\n");
 return;
 }
 for(int i=0;i<26;i++)
 {
 int posa=lasta[n][i],posb=lastb[m][i];
 if(f[posa+1][posb+1]==res)
 {
 ans[cnt++]=i;
 dfs(res-1,posa-1,posb-1);
 cnt--;
 }
 }
}
int main()
{
    scanf("%s%s",a,b);
    int n=strlen(a),m=strlen(b);
    for(int i=0;i<n/2;i++)swap(a[i],a[n-i-1]);
 for(int i=0;i<m/2;i++)swap(b[i],b[m-i-1]); 
 for(int i=1;i<=n;i++)
 for(int j=1;j<=m;j++)
 if(a[i-1]==b[j-1])
 f[i][j]=f[i-1][j-1]+1;
 else f[i][j]=max(f[i-1][j],f[i][j-1]);

 memset(lasta,-1,sizeof(lasta));
 memset(lastb,-1,sizeof(lastb));
 for(int i=0;i<n;i++)
 {
 for(int j=i;j>=0;j--)
if(lasta[i][a[j]-'A']==-1)
 lasta[i][a[j]-'A']=j;
 }
    for(int i=0;i<m;i++)
 {
 for(int j=i;j>=0;j--)
if(lastb[i][b[j]-'A']==-1)
 lastb[i][b[j]-'A']=j;
 }
 dfs(f[n][m],n-1,m-1);
    return 0;
} 
View Code

 

posted @ 2017-03-20 17:37  Dijkstra·Liu  阅读(421)  评论(2编辑  收藏  举报