[bzoj2423]最长公共子序列

然而不会计数dp。。看的题解。。http://blog.csdn.net/neither_nor/article/details/52190114

普通统计LCS长度的n^2DP式,大家都会……

然后统计一下方案数

a[i]!=b[j]的时候,判一下f[i][j]和f[i-1][j],f[i][j-1]分别相不相等,如果相等就加上对应的方案数,再判和f[i-1][j-1]是否相等,相等就再减去[i-1][j-1]的方案数

a[i]==b[j]的时候,用[i-1][j-1]的方案数,然后如果f[i-1][j]或者[i][j-1]和f[i][j]相等的话,也加上对应的方案数

事实上还有一些比较傻逼的做法……用f[i][j]表示公共子序列的末尾必须在i位置和j位置的LCS长度,然后用树状数组找之前的f最大值,用最大值+1更新f,再查询之前f等于这个最大值的点的方案数的和,赋给这里的方案数……复杂度多个log,也可以过……

dp的方法勉强看懂。。后面那个树状数组的方法什么鬼。。

 

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 using namespace std;
 7 
 8 const int MOD=100000000;
 9 
10 char a[6000],b[6000];
11 int f[2][6000],ct[2][6000],I,J;
12 
13 int main(){
14     scanf("%s%s",a+1,b+1);
15     int len1=strlen(a+1)-1,len2=strlen(b+1)-1;
16     for(int i=1;i<=len1;i++){
17         for(int j=1;j<=len2;j++){
18             if(a[i]==b[j]){  
19                 f[i&1][j]=f[i&1^1][j-1]+1;  
20                 ct[i&1][j]=(ct[i&1^1][j-1]+(f[i&1^1][j]==f[i&1][j])*ct[i&1^1][j]+(f[i&1][j-1]==f[i&1][j])*ct[i&1][j-1])%MOD;  
21                 if(!f[i&1^1][j-1])ct[i&1][j]++;
22             }else{  
23                 f[i&1][j]=max(f[i&1^1][j],f[i&1][j-1]);  
24                 ct[i&1][j]=(-(f[i&1^1][j-1]==f[i&1][j])*ct[i&1^1][j-1]+(f[i&1^1][j]==f[i&1][j])*ct[i&1^1][j]+(f[i&1][j-1]==f[i&1][j])*ct[i&1][j-1]+MOD)%MOD;  
25             }      
26         }
27     }
28     printf("%d\n%d\n",f[len1&1][len2],ct[len1&1][len2]);
29 }
View Code

 

posted @ 2017-01-09 20:57  KingSann  阅读(108)  评论(0)    收藏  举报