您的位置:首页 > 其它

【NOIP2015】【洛谷2679】子串

2017-05-11 00:45 197 查看
链接:https://www.luogu.org/problem/show?pid=2679

题解:

1.求方案数,结合数据范围,可以考虑用DP解

2.令f[i][j][k][0/1]表示A串用了前i个字符,B串已覆盖前j个字符,目前为止已经选了k个子串,最后的0/1表示A串的这个字符选了没有(0没选,1选了)。

3.若当前字符选了,显然当且仅当a[i]=b[j]的时候它才有意义,否则f[i][j][k][1]=0。

到这个状态有三种方法:

(1). 上一位不选,新开一个子串

(2). 上一位选了,延续这个子串

(3). 上一位选了,新开一个子串

根据dp数组的定义,可以得到

f[i][j][k][1]=f[i-1][j-1][k-1][0]+f[i-1][j-1][k][1]+f[i-1][j-1][k-1][1]。

4.若当前字符不选。

(1). 上一位不选,现在仍然不选

(2). 上一位选了,现在不选

故f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]。

总的方程式

f[i][j][k][1]=f[i-1][j-1][k-1][0]+f[i-1][j-1][k][1]+f[i-1][j-1][k-1]1

f[i][j][k][1]=0(a[i]!=b[j])

f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]

边界:f[0][0][0][0]=1。

最终答案:f
[m][k][0]+f
[m][k][1]。

复杂度O(nmk)

考虑到空间可能爆掉,用滚动数组压掉第一维即可

写的很心累QAQ

各种细节错QAQ

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MOD 1000000007
#define Maxn 2020
int f[2][Maxn][Maxn][2];
int main()
{
//  freopen("2015substring.in","r",stdin);
//  freopen("2015substring.out","w",stdout);
int n,m,k,d=1;
char a[Maxn],b[Maxn];
scanf("%d %d %d %s %s",&n,&m,&k,a+1,b+1);
f[0][0][0][0]=1;
for(int i=1;i<=n;i++,d=!d)
for(int j=0;j<=i&&j<=m;j++)
for(int h=0;h<=k&&h<=j&&h<=i;h++)
{
f[d][j][h][0]=0;
if(i-1>=j)
{
(f[d][j][h][0]+=f[!d][j][h][0])%=MOD;
(f[d][j][h][0]+=f[!d][j][h][1])%=MOD;
}
f[d][j][h][1]=0;
if(j&&a[i]==b[j])
{
if(h)
{
(f[d][j][h][1]+=f[!d][j-1][h-1][0])%=MOD;
(f[d][j][h][1]+=f[!d][j-1][h-1][1])%=MOD;
}
(f[d][j][h][1]+=f[!d][j-1][h][1])%=MOD;

}
}
printf("%d\n",f[!d][m][k][0]+f[!d][m][k][1]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: