【NOIP2015提高組Day2】子串
阿新 • • 發佈:2019-02-08
輸入1:
6 3 1
aabaab
aab
輸入2:
6 3 2
aabaab
aab
輸入3:
6 3 3
aabaab
aab
輸出1:
2
輸出2:
7
輸出3:
7
小結
我寫這篇部落格是為了記住這樣的套路:字串匹配可用DP。(這是NOIP的題,考場我沒有經驗沒有想到DP,但是有人很屌的A了)
我們設
我們可以推出方程:
這個很好理解:
然後看匹配的,有三種情況:
首先必須滿足的條件是A[i]==B[i];
當前第i位與第j位匹配,上一位的情況有:
- 與B的第j位匹配,但是不分段;
F[i−1][j−1][k][1] - 與B的第j位匹配,分段;
F[i−1][j−1][k−1][1] - 不與B的第j位匹配;
F[i−1][j−1][k][0]
則轉移結束。
當然,初始化:首先F[0][0][0][0]=1; ,毋庸置疑的,但是由於每個點都可以成為第一個與B匹配的點,所以F[i][0][0][0]=1;
打一個滾動就可以了。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,K,ans;
string A,B;
long long f[2][201][201][2];
int main()
{
freopen("substring.in","r",stdin);
freopen("substring.out","w",stdout);
scanf("%d%d%d",&n,&m,&K);
cin>>A;
cin>>B;int i,j,k,now=0 ,last=1;
f[0][0][0][0]=1;
for (i=1;i<=n;++i)
{
swap(now,last);
f[now][0][0][0]=1;
for (j=1;j<=m;++j)
for (k=1;k<=K;++k)
{
f[now][j][k][0]=(f[last][j][k][0]+f[last][j][k][1])%1000000007;
if(A[i-1]==B[j-1])
f[now][j][k][1]=((f[last][j-1][k][1]+f[last][j-1][k-1][1])%1000000007+f[last][j-1][k-1][0])%1000000007;
else f[now][j][k][1]=0;
}
}
printf("%lld\n",(f[now][m][K][0]+f[now][m][K][1])%1000000007);
}