[BZOJ 2423] [HAOI2010] 最长公共子序列
2015-06-17 17:45
330 查看
2423: [HAOI2010]最长公共子序列
Time Limit: 10 SecMemory Limit: 128 MBDescription
字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列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
47
【题解】
参照一般的最长公共子序列的做法
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
相关文章推荐
- linux 内核驱动加载过程中 向文件系统中的文件进行读写操作
- Oracle对象的死锁
- git学习
- BeautifulSoup下载给定URL里的图片(二)
- oracle 判断字符串是否日期格式
- 城市列表的实例
- 【JavaScript 7—基础知识点】:BOM
- redis本地安装
- 【JavaScript 7—基础知识点】:BOM
- typedef
- 开发者如何利用工具快速开发出完美的App
- 179在屏幕中绘制一个三角形
- 安装UML工具:EA(Enterprise Architect)+首次使用EA
- Android数据篇
- 如何修改数据?alter和update的区别?
- Ubuntu server下搭建Maven私服Nexus
- ArcGIS Python批量插值、裁切
- 关于checkbox值回显
- 哪些人不能重用或者聘用
- 关于“The type **** is not accessible due to restriction on required library”问题的解决