luogu2679 [NOIp2015]子串 (dp)

时间:2023-03-09 02:01:54
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,而且要开滚动数组

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define lowb(x) ((x)&(-(x)))
#define REP(i,n0,n) for(i=n0;i<=n;i++)
#define PER(i,n0,n) for(i=n;i>=n0;i--)
#define MAX(a,b) ((a>b)?a:b)
#define MIN(a,b) ((a<b)?a:b)
#define CLR(a,x) memset(a,x,sizeof(a))
#define rei register int
using namespace std;
typedef long long ll;
const int maxn=,maxm=,mod=1e9+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,M,K;
int f[][maxm][maxm][],ans=;
char A[maxn],B[maxm]; int main(){
// freopen("testdata.in","r",stdin);
rei i,j,k;
N=rd(),M=rd(),K=rd();
scanf("%s%s",A+,B+);
f[][][][]=(A[]==B[]);
f[][][][]=;
ans=f[][K][M][];
bool b=;
for(i=;i<=N;i++){
for(j=;j<=min(K,i);j++){
for(k=;k<=min(M,i);k++){
if(A[i]==B[k]&&j>) f[b][j][k][]=(0ll+f[b^][j-][k][]+f[b^][j][k-][]+f[b^][j-][k-][])%mod;
else f[b][j][k][]=;
f[b][j][k][]=(f[b^][j][k][]+f[b^][j][k-][])%mod;
// printf("%d %d %d %d %d\n",i,j,k,f[i][j][k][0],f[i][j][k][1]);
}
}
if(i>=K&&i>=M) ans=(ans+f[b][K][M][])%mod;
b^=;
}
printf("%d\n",ans);
return ;
}