noip 2015 子串(dp+滾動陣列)
阿新 • • 發佈:2019-01-29
題目大意:給定兩個字串A,B(都是由a,b組成)(長度分別為n,m);你可以在字串A中任擷取k個字串按擷取順序組成字串B,問能擷取的方案數
動態規劃;
s[i][j][k]:字串A正要處理第i項了,陣列B匹配正要第j項,已經截取了k個字串,總方案數;
f[i][j][k]:字串A正要處理第i項了,陣列B匹配正要第j項了,已經截取了k個字串,且第k個字串必須包含A的第i項的總方案數;
考慮怎麼轉移
當a[i]=b[j]時;
f[i][j][k]=f[i-1][j-1][k]+s[i-1][j-1][k-1];//把a[i]放進以前截好的的第k段的末尾 和 a[i]單獨成第k段。
s[i][j][k]=s[i-1][j-1][k]+f[i][j][k];
當a[i]!=b[j]時;
f[i][j][k]=0;//第k段,不可能有a[i].
s[i][j][k]=s[i-1][j][k];(s[i][j][k]=s[i-1][j][k] + 0);
//注意-1超邊界
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; #define fo(a,b,c) for(int a=(b);a<=(c);a++) const int mod=1000000007; char a[1005],b[205]; int s[2][205][205],f[2][205][205],n,m,h; long long ans = 0; void solve() { int pre=1; int now=0; s[pre][0][0]=1; fo(i,1,n) { s[now][0][0]=1; fo(j,1,m) { fo(k,1,min(h,j)) if(a[i-1]==b[j-1]) { f[now][j][k]=(f[pre][j-1][k]+s[pre][j-1][k-1])%mod; s[now][j][k]=(f[now][j][k]+s[pre][j][k])%mod; } else {s[now][j][k]=s[pre][j][k]; f[now][j][k]=0; } } pre^=1; now^=1; } cout<<s[pre][m][h]%mod; } int main() { //freopen("ha.in","r",stdin); scanf("%d%d%d%s%s",&n,&m,&h,a,b); solve(); return 0; }