luogu2679 [NOIp2015]子串 (dp)
设f[i][j][k][b]表示在A串第i位、这是第j组、B串第k位、i号选不选(b=0/1)
那么就有$f[i][j][k][1]=(A[i]==B[k])*(f[i-1][j-1][k][0]+f[i-1][j][k-1][1]+f[i-1][j-1][k-1][1])$,$f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k-1][1]$
注意不要爆int,而且要开滚动数组
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define lowb(x) ((x)&(-(x))) 4 #define REP(i,n0,n) for(i=n0;i<=n;i++) 5 #define PER(i,n0,n) for(i=n;i>=n0;i--) 6 #define MAX(a,b) ((a>b)?a:b) 7 #define MIN(a,b) ((a<b)?a:b) 8 #define CLR(a,x) memset(a,x,sizeof(a)) 9 #define rei register int 10 using namespace std; 11 typedef long long ll; 12 const int maxn=1010,maxm=220,mod=1e9+7; 13 14 inline ll rd(){ 15 ll x=0;char c=getchar();int neg=1; 16 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 17 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 18 return x*neg; 19 } 20 21 int N,M,K; 22 int f[2][maxm][maxm][2],ans=0; 23 char A[maxn],B[maxm]; 24 25 int main(){ 26 // freopen("testdata.in","r",stdin); 27 rei i,j,k; 28 N=rd(),M=rd(),K=rd(); 29 scanf("%s%s",A+1,B+1); 30 f[1][1][1][1]=(A[1]==B[1]); 31 f[1][0][1][0]=1; 32 ans=f[1][K][M][1]; 33 bool b=0; 34 for(i=2;i<=N;i++){ 35 for(j=0;j<=min(K,i);j++){ 36 for(k=1;k<=min(M,i);k++){ 37 if(A[i]==B[k]&&j>0) f[b][j][k][1]=(0ll+f[b^1][j-1][k][0]+f[b^1][j][k-1][1]+f[b^1][j-1][k-1][1])%mod; 38 else f[b][j][k][1]=0; 39 f[b][j][k][0]=(f[b^1][j][k][0]+f[b^1][j][k-1][1])%mod; 40 // printf("%d %d %d %d %d\n",i,j,k,f[i][j][k][0],f[i][j][k][1]); 41 } 42 } 43 if(i>=K&&i>=M) ans=(ans+f[b][K][M][1])%mod; 44 b^=1; 45 } 46 printf("%d\n",ans); 47 return 0; 48 }