很自然想到DP
这道题使我意识到自己的DP功力还有很大不足
用f[i][j][k][0/1]表示A串到i位,B串到j位,A串分为了k部分,第i位是否匹配进B串的方案数(一般套路)
优化:滚动数组,设置pre,now,
教训:
1、别图省事,把该写全的写全
2、找个好弄一点的DP边界
3、一个方程不大好转移就换一个,
4、经常从i-1或j-1转移过来
5、看数据范围猜循环
看到DP题时:
想状态,想转移,想边界,想决策();
#include<iostream> #include<cstdio> #include<cstring> #define N 1009 #define M 209 #define mod 1000000007 using namespace std; int n,m,KK; char s[N]; int a[N],b[M]; int f[2][M][M][2]; int cnt; int pre,now; int main(){ cin>>n>>m>>KK; scanf("%s",s); for(int i=1;i<=n;++i)a[i]=s[i-1]; scanf("%s",s); for(int i=1;i<=m;++i)b[i]=s[i-1]; pre=0;now=1; for(int i=1;i<=n;++i){ f[now][1][1][0]=cnt; if(a[i]==b[1]){ f[now][1][1][1]=1; ++cnt; }else{ f[now][1][1][1]=0; } for(int j=2;j<=m;++j){ for(int k=1;k<=KK;++k){ f[now][j][k][0]=(f[pre][j][k][0]+f[pre][j][k][1])%mod; if(a[i]==b[j])f[now][j][k][1]=(f[pre][j-1][k-1][1]+f[pre][j-1][k-1][0]+(long long)f[pre][j-1][k][1])%mod; else f[now][j][k][1]=0; } } //memset(f[pre],0,sizeof(f[pre])); swap(pre,now); } printf("%d\n",(f[pre][m][KK][0]+f[pre][m][KK][1])%mod); return 0; }
时间: 2024-09-29 21:28:23