码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2423[HAOI2010]最长公共子序列

时间:2016-07-22 22:51:57      阅读:291      评论:0      收藏:0      [点我收藏+]

标签:

bzoj2423[HAOI2010]最长公共子序列

题意:

求两个字符串的最长公共子序列长度和个数。

题解:

dp,设f[i][j]表示x串i位到末位,y串j位到末位的最长长度,g[i][j]表示x串i位到末位,y串j位到末位的最长长度的个数,方程:

x[i]==y[j]:f[i][j]=f[i+1][j+1]+1 g[i][j]=g[i+1][j+1]+(f[i][j]==f[i+1][j])*g[i+1][j]+(f[i][j]==f[i][j+1])*g[i][j+1];
x[i]!=y[j]:f[i][j]=max(f[i+1][j],f[i][j+1]);
g[i][j]=(f[i][j]==f[i+1][j])*g[i+1][j]+(f[i][j]==f[i][j+1])*g[i][j+1]-(f[i][j]==f[i+1][j]&&f[i][j]==f[i][j+1]&&f[i][j]==f[i+1][j+1])*g[i+1][j+1];

边界就是g[xn+1][1..yn+1]=1和g[xn][yn+1]=1,滚动一下就行。

反思:蒟蒻wa了好多发,包括红色部分漏了,模的时候没有考虑负数和边界条件写错,但根本原因还是对dp的循环写法的不熟练(以前总是写记忆化搜索,导致现在一要滚动数组就GG),尤其是边界如何处理方面。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 #define dec(i,j,k) for(int i=j;i>=k;i--)
 6 #define maxn 6000
 7 #define ll long long
 8 #define mod 100000000
 9 using namespace std;
10 
11 char sx[maxn],sy[maxn]; int nx,ny;
12 ll fx[maxn],fy[maxn],gx[maxn],gy[maxn];
13 int main(){
14     scanf("%s",sx+1); scanf("%s",sy+1); nx=strlen(sx+1)-1; ny=strlen(sy+1)-1;
15     inc(i,1,ny+1)gx[i]=1; gy[ny+1]=1;
16     dec(i,nx,1){
17         dec(j,ny,1){
18             if(sx[i]==sy[j]){
19                 fy[j]=fx[j+1]+1; gy[j]=gx[j+1]+(fy[j]==fx[j])*gx[j]+(fy[j]==fy[j+1])*gy[j+1];
20                 gy[j]%=mod;
21             }else{
22                 fy[j]=max(fx[j],fy[j+1]);
23                 gy[j]=(fy[j]==fx[j])*gx[j]+(fy[j]==fy[j+1])*gy[j+1]-(fy[j]==fx[j]&&fy[j]==fy[j+1]&&fy[j]==fx[j+1])*gx[j+1];
24                 gy[j]+=mod; gy[j]%=mod;
25             }
26         }
27         swap(fx,fy); swap(gx,gy);
28     }
29     printf("%lld\n%lld",fx[1],gx[1]); return 0;
30 }

 

20160722

bzoj2423[HAOI2010]最长公共子序列

标签:

原文地址:http://www.cnblogs.com/YuanZiming/p/5697208.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!