(Sol)
不知道为啥看起来就很(dp)的亚子.我们关心的只有(A)串当前用到哪一个,(B)串已经匹配到哪个位置,已经匹配的被分成了多少段.所以设(f_{i,j,k,0/1})表示(A)串用到第(i)个,(B)串已经匹配到第(j)个,分成了(k)段,最后一段是否被断开.
瞎转移一波(这里就不详细讲了,看代码也很容易懂)就获得了(90pts)的好成绩.还有(10pts)呢?数组开不下吖(QwQ).我开始居然没想到滚动数组,还乱搞了一波(map),发现(f_{i,j,k,0/1})一定是转移到(f_{i+1,j',k',0/1}),所以可以滚动第一维,要注意在循环开始的时候清空一维数组.
(Code)
#include<bits/stdc++.h>
#define il inline
#define Ri register int
#define go(i,a,b) for(Ri i=a;i<=b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
il int read()
{
Ri x=0,y=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*y;
}
const int N=1005,mod=1000000007;
int n,m,kk,as,f[2][205][205][2];char s1[N],s2[N];
il void inc(Ri &x,Ri y){x+=y;if(x>=mod)x-=mod;}
int main()
{
n=read(),m=read(),kk=read();
scanf("%s",s1+1);scanf("%s",s2+1);
f[0][0][0][0]=1;
go(ii,0,n)
{
Ri i=ii&1;
mem(f[i^1],0);
go(j,0,min(m,ii))
go(k,0,kk)
go(g,0,1)
{
if(!f[i][j][k][g])continue;
inc(f[i^1][j][k][0],f[i][j][k][g]);
if(s1[ii+1]==s2[j+1])
{
inc(f[i^1][j+1][k+1][1],f[i][j][k][g]);
if(g)inc(f[i^1][j+1][k][1],f[i][j][k][g]);
}
}
inc(as,f[i][m][kk][1]);
}
printf("%d
",as);
return 0;
}