您的位置:首页 > 其它

[BZOJ 2423] [HAOI2010] 最长公共子序列

2015-06-17 17:45 330 查看

2423: [HAOI2010]最长公共子序列

Time Limit: 10 SecMemory Limit: 128 MB

Description

字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij = yj。例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。对给定的两个字符序列,求出他们最长的公共子序列长度,以及最长公共子序列个数。

Input

第1行为第1个字符序列,都是大写字母组成,以”.”结束。长度小于5000。
第2行为第2个字符序列,都是大写字母组成,以”.”结束,长度小于5000。

Output

第1行输出上述两个最长公共子序列的长度。
第2行输出所有可能出现的最长公共子序列个数,答案可能很大,只要将答案对100,000,000求余即可。

Sample Input

ABCBDAB.

BACBBD.

Sample Output

4

7
【题解】

参照一般的最长公共子序列的做法

if s1[i]==s2[j] then f[i][j]=f[i-1][j-1]+1

else f[i][j]=max(f[i][j-1],f[i-1][j])

然后我们用g[i][j]来表示方案数。

对于s1[i]==s2[i]

g[i][j]=g[i-1][j-1]+k1*g[i-1][j]+k2*g[i][j-1]

f[i][j]=f[i-1][j] then k1=1 else k1=0;

f[i][j]=f[i][j-1] then k2=1 else k2=0;

对于s1[i]!=s2[i]

g[i][j]=g[i-1][j-1]+k1*g[i-1][j]+k2*g[i][j-1]-k3*g[i-1][j-1]

f[i][j]=f[i-1][j] then k1=1 else k1=0;

f[i][j]=f[i][j-1] then k2=1 else k2=0;

f[i][j]=f[i-1][j-1] then k3=1 else k3=0;

然后上去发现MLE!!!

就开了开滚动数组TAT

然后写跪了QAQ

#include <stdio.h>
#include <string.h>
#include<iostream>
#define max(a,b) a>b?a:b
using namespace std;
const int MOD=100000000;
int f[2][5001],g[2][5001];
char s1[5001],s2[5002];
int len1,len2;
int main() {
scanf("%s%s",s1,s2);
len1=strlen(s1);
len2=strlen(s2);
for (int i=len1-1;i>=1;--i) s1[i]=s1[i-1];
for (int i=len2-1;i>=1;--i) s2[i]=s2[i-1];
len1--;len2--;
int pre=0,now=1;
for (int i=1;i<=len2;i++)
g[0][i]=1;
g[pre][0]=1;
for (int i=1;i<=len1;++i) {
for (int j=1;j<=len2;++j) f[now][j]=g[now][j]=0;
g[now][0]=1;
for (int j=1;j<=len2;++j)
if(s1[i]==s2[j]) {
f[now][j]=f[pre][j-1]+1;
g[now][j]=g[pre][j-1],g[now][j]%=MOD;
if (f[now][j]==f[pre][j]) g[now][j]+=g[pre][j],g[now][j]%=MOD;
if (f[now][j]==f[now][j-1]) g[now][j]+=g[now][j-1],g[now][j]%=MOD;
}
else {
f[now][j]=max(f[pre][j],f[now][j-1]);
if (f[now][j]==f[pre][j]) g[now][j]+=g[pre][j],g[now][j]%=MOD;
if (f[now][j]==f[now][j-1]) g[now][j]+=g[now][j-1],g[now][j]%=MOD;
if (f[now][j]==f[pre][j-1]) g[now][j]-=g[pre][j-1],g[now][j]=(g[now][j]+MOD)%MOD;
}//cout<<i<<" "<<j<<" "<<f[now][j]<<" "<<g[now][j]<<endl;}
int t=pre;pre=now;now=t;
}
printf("%d\n%d\n",f[pre][len2],g[pre][len2]);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: