您的位置:首页 > 其它

[luogu-2679]noip2015day2-T2 子串 题解

2017-09-03 16:30 225 查看
题目传送门

题意解析:题目给了两个字符串A和B,求由m个A的子串连接起来成为B的方案数是多少。

My opinion:看到这题目的时候想到了最长公共子串,dp嘛。我一开始想到了一个三维状态,dp[i][j][k]表示A的匹配到第i个字符,B匹配到第j个字符,一共是k个子串的方案数,但是这样子做还需要多一重循环来枚举,明显超时。所以为了防TLE,使用了万金油——加维,dp[i][j][k][0/1]中的[0/1]来表示这个字符是否属于同一个子串。然而后来我写不出来(有dalao告诉我这样可以,但是我就是菜到写不出来),所以为了去掉那一维,我采取了用s[i][j][k]来记录答案的前缀和(并且将i和j的状态换了一下),这样就可以省去一重枚举了。

总结:

1、输入

2、dp

方程为



奇怪的代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
#define Clear(a,x) memset(a,x,sizeof(a))
#define ll long long
#define INF 2000000000
#define eps 1e-8
using namespace std;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=1005,maxm=205,mod=1000000007;
char A[maxn],B[maxm];
int f[2][maxn][maxm],s[2][maxn][maxn];
int n,m,K;
int main(){
n=read(),m=read(),K=read();
scanf("%s",A+1);
scanf("%s",B+1);
rep(j,0,n)
s[0][j][0]=1;
A[0]=' ',B[0]=' ';
rep(i,1,m){
int now=i%2,last=(i-1)%2;
Clear(f[now],0);
Clear(s[now],0);
rep(j,1,n)
rep(k,1,K)
if (A[j]==B[i]){
if (A[j-1]==B[i-1]||i==1)
f[now][j][k]+=f[last][j-1][k],f[now][j][k]%=mod;
f[now][j][k]+=s[last][j-1][k-1],f[now][j][k]%=mod;
s[now][j][k]+=s[now][j-1][k]+f[now][j][k],s[now][j][k]%=mod;
}else s[now][j][k]+=s[now][j-1][k]+f[now][j][k],s[now][j][k]%=mod;
}
printf("%d\n",s[m%2]
[K]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: