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
",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
",ans);
47     return 0;
48 }
原文地址:https://www.cnblogs.com/Ressed/p/9703724.html