题解 P2679 【子串】
透彻是多么重要
今天考试推了半天的方程 没有推出来 (∏_∏)
蒟蒻已无语 dalao狂鄙视
------------------------------------吐槽时间----------------------------------------
首先 这道题看上去是一道字符串匹配题 AC自动机orKMP
可是 再多看看题面 不是
我们想到了什么 DP
考虑当前匹配成功与匹配不成功
分别用
ans[i][j][k] 记录当前 A[i]不论等不等于B[j] 我们可以选用也可以不选用 使用k个子串方案数
res[i][j][k] 记录当前 A[i]==B[j] 并且我们选用A[i]和B[j] 方案数 使用k个子串方案数
得到状态转移方程
if(A[i]==B[j])
res[i][j][k]=(ans[i-1][j-1][k-1]+res[i-1][j-1][k])%mod;
//ans[i-1][j-1][k-1] 我们把当前匹配字符单独算做一个子串
//res[i-1][j-1][k] 我们把当前匹配字符与上面的和为一个子串
else res[i][j][k]=0;
//不成则为零
ans[i][j][k]=(res[i][j][k]+ans[i-1][j][k])%mod;
//res[i][j][k] 使用当前字符
//ans[i-1][j][k] 不使用当前字符
貌似一切大吉了??
可是 ans[1000][20][20]
保底都开不下 更何况还要开大以防止RE
考虑滚动数组
if(A[i] == B[j])
res[now][j][p]=(res[now^1][j-1][p]+ans[now^1][j-1][p-1])%mod;
else res[now][j][p]=0;
ans[now][j][p]=(ans[now^1][j][p]+res[now][j][p])%mod;
因为状态转移时 只需调用 i and i-1
所以只需在1和0之间滚动即可
dalao勿喷
CODE:
#pragma GCC optimize(3)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#define ll long long
#define inf 0x7fffffff
#define mod 1000000007
#define N 500008
#define IL inline
#define M 1008611
#define D double
#define ull unsigned long long
#define R register
using namespace std;
template<typename T>void read(T &a)
{
T x=0,f=1;char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')f=0;ch=getchar();
}
while(isdigit(ch))
{
x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
}
a=f?x:-x;
}
/*-------------OI使我快乐-------------*/
int n,m,k,now;
int ans[3][1010][1010],res[3][1010][1010];
char A[1010],B[1010];
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n);read(m);read(k);
scanf("%s%s",A+1,B+1);
ans[0][0][0]=1;now=1;
for(R int i=1;i<=n;++i){
ans[now][0][0]=1;
for(R int j=1;j<=m;++j)
for(R int p=1;p<=k;++p){
if(A[i] == B[j]) res[now][j][p]=(res[now^1][j-1][p]+ans[now^1][j-1][p-1])%mod;
else res[now][j][p]=0;
ans[now][j][p]=(ans[now^1][j][p]+res[now][j][p])%mod;
}
now^=1;
}
printf("%d\n",ans[now^1][m][k]);
// fclose(stdin);
// fclose(stdout);
return 0;
}
NOIP 2018 即将到来
不透彻的赶紧透彻 没准会RP++