题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2423
题解:唔,我其实也不会,然后去看了题解。。。
大概意思是我们不仅仅用f[i][j]来表示最长公共子序列的长度,还要用一个g[i][j]来表示方案数,具体的话程序里写吧。。
#include<iostream> #include<cstdio> #include<cstring> #include<string> #define mod 100000000; using namespace std; char a[10000],b[10000]; long long g[2][6000],f[2][6000]; int q,p2,p1,k1,k2,k3; int main() { scanf("%s%s",a+1,b+1); int p1=0; int n=strlen(a+1)-1,m=strlen(b+1)-1;//记录输入的长度 for (int i=0;i<=m;i++) g[0][i]=1;//一边没有,另一边为一个的方案数为1; g[1][0]=1; //这道题需要用滚动数组,所以我们只需计录之前的状态就可以了 for (int i=1;i<=n;i++) { p2=p1; p1=p1^1; //这里我本来用的是减法,结果悲催的发现时间超限了。。。所以还是乖乖 //用位运算吧,p1表示当前状态,p2表示上一次的状态。 for (int j=1;j<=m;j++) if (a[i]==b[j])//如果说当前相等的话 { f[p1][j]=max(f[p1][j],f[p2][j-1]+1); //这一次的方案数一定包括f[p2][j-1]; if (f[p1][j]==f[p1][j-1]) k1=1; else k1=0; if (f[p1][j]==f[p2][j]) k2=1; else k2=0; //继续判断其他情况如果相等的话才能加上相应的方案数 g[p1][j]=(g[p2][j-1]+k1*g[p1][j-1]+k2*g[p2][j])%mod; } else { f[p1][j]=max(f[p1][j-1],f[p2][j]); if (f[p1][j]==f[p1][j-1]) k1=1; else k1=0; //如果公共序列的长度没变,但是位置已经进行了移动,那就 加上上次的方案数。 if (f[p1][j]==f[p2][j]) k2=1; else k2=0; if (f[p1][j]==f[p2][j-1]) k3=-1; else k3=0; g[p1][j]=(k3*g[p2][j-1]+k1*g[p1][j-1]+k2*g[p2][j])%mod; } } cout<<f[p1][m]<<endl; cout<<g[p1][m]<<endl; return 0; }