[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 }