版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
Analysis
- 首先这个名字“字符串dp”就是我乱取的……反正在字符串上搞嘛
- 第二次做,在知道这是dp的情况下,依旧没有分析出来。。在大致瞥了一眼定义后,仍旧没有转移对。菜是十大原罪之首
考虑两个字符串
一般都需要在状态中记录下当前分别在各个串的哪个位置
那么前两维我们就定义出来了
表示在A串中进行到前i位,B串进行到前j位
等等,这样的定义很不明确
侯神说dp状态定义一定要尽量明确
什么叫做进行?
换一个
匹配到B串的第j位
再考虑题目中的信息,我们还需要记录提取出了几个串
加一维[k]表示提取出了k个串
最后考虑转移
由于串是要连续的,所以在转移的时候我们得知道上一个位置选没有
oh,再加一维[0/1](反正只要需要就加加加加)
综上所述,我们定义出来的状态长这样:
转移嘞?
如果
这个位置不选。
如果
这个位置要选,肯定得满足
哈哈,完啦
等等,好像空间开不下??(应该能过)
滚动一发,噢啦
(如果要滚动,记得枚举顺序反一下。因为要调用之前的信息)
还有一种没有记0/1状态的定义
其实本质是一样的就是看当前这一位
与
相等的时候,是否独成一串
Code
#include<bits/stdc++.h>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define nc getchar
inline int read(){
int x=0,f=1;
char ch=nc();
while(!isdigit(ch)&&ch!='-')ch=nc();
if(ch=='-')ch=nc(),f=-1;
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-48;ch=nc();}
return x*f;
}
const int N=1002,M=202;
typedef long long ll;
const int mod=1e9+7;
ll dp[M][M][2];
int n,m,k;
char a[N],b[M];
int main(){
n=read();m=read();k=read();
scanf("%s",a+1);
scanf("%s",b+1);
dp[0][0][0]=1;
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--){
if(a[i]!=b[j]){
for(int l=0;l<=k;l++){
dp[j][l][0]=(dp[j][l][0]+dp[j][l][1])%mod;
dp[j][l][1]=0;
}
}
else{
dp[j][0][0]=(dp[j][0][0]+dp[j][0][1])%mod;
for(int l=k;l>=1;l--){
dp[j][l][0]=(dp[j][l][0]+dp[j][l][1])%mod;
dp[j][l][1]=(dp[j-1][l-1][0]+dp[j-1][l-1][1]+dp[j-1][l][1])%mod;
}
}
}
printf("%lld",(dp[m][k][0]+dp[m][k][1])%mod);
return 0;
}