【NOIP2015提高组Day2】子串

题面

Description

在这里插入图片描述

Input

在这里插入图片描述

Output

在这里插入图片描述

Sample Input

输入1:

6 3 1
aabaab
aab

输入2:

6 3 2
aabaab
aab

输入3:

6 3 3
aabaab
aab

Sample Output

输出1:

2

输出2:

7

输出3:

7
在这里插入图片描述

Data Constraint

在这里插入图片描述

思路

这道题我们可以考虑用 D P DP DP来做。
f i , j , k , 0 f_{i,j,k,0} fi,j,k,0表示a序列枚举到i位置,b序列枚举到j位置,选了k个子串,当前不选,则 f i , j , k , 1 f_{i,j,k,1} fi,j,k,1表示选。


接着我们可以分两种情况讨论:

  1. a i ! = b j a_i!=b_j ai!=bj
    当前转移方程即为:
    f i , j , k , 1 = 0 f_{i,j,k,1}=0 fi,j,k,1=0
    f i , j , k , 0 = f i − 1 , j , k , 0 + f i − 1 , j , k , 1 f_{i,j,k,0}=f_{i-1,j,k,0}+f_{i-1,j,k,1} fi,j,k,0=fi1,j,k,0+fi1,j,k,1

  2. a i = b j a_i=b_j ai=bj
    当前转移方程即为:
    f i , j , k , 0 = f i − 1 , j , k , 0 + f i − 1 , j , k , 1 f_{i,j,k,0}=f_{i-1,j,k,0}+f_{i-1,j,k,1} fi,j,k,0=fi1,j,k,0+fi1,j,k,1
    当前选的情况又可以分为三种情况讨论:
    1 ) 1) 1) .前面有子串,不用新增
           f i − 1 , j − 1 , k , 1 ~~~~~~f_{i-1,j-1,k,1}       fi1,j1,k,1
    2 ) 2) 2) .前面有子串,但新增一子串
           f i − 1 , j − 1 , k − 1 , 1 ~~~~~~f_{i-1,j-1,k-1,1}       fi1,j1,k1,1
    3 ) 3) 3) .前面一个无子串,新增一子串
           f i − 1 , j − 1 , k − 1 , 0 ~~~~~~f_{i-1,j-1,k-1,0}       fi1,j1,k1,0
    将上述方案加起来即为 f i , j , k , 1 f_{i,j,k,1} fi,j,k,1的转移式了。


答案: f n , m , k , 0 + f n , m , k , 1 f_{n,m,k,0}+f_{n,m,k,1} fn,m,k,0+fn,m,k,1
初始化: f 0 , 0 , 0 , 0 = f 1 , 0 , 0 , 0 = 1 f_{0,0,0,0}=f_{1,0,0,0}=1 f0,0,0,0=f1,0,0,0=1


然而我们会发现如果这样做的话,我们就会

在这里插入图片描述

于是我们可以考虑开一个滚动数组,因为第 i i i位只用考虑第 i − 1 i-1 i1位的数,所以我们只需要将 i i i位置开2位。

Code

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define mod 1000000007
using namespace std;
int n,m,s,len,len1,ans;
char a[1005],b[205];
long long f[2][205][205][2];
int main()
{
    
    
	freopen("substring.in","r",stdin);
	freopen("substring.out","w",stdout);
	scanf("%d%d%d",&n,&m,&s);
	scanf("%s",a+1);
	scanf("%s",b+1);
	f[0][0][0][0]=f[1][0][0][0]=1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			for(int k=1;k<=s;k++)
			{
    
    
				if(a[i]!=b[j])
				{
    
    
					f[i%2][j][k][1]=0;
					f[i%2][j][k][0]=(f[(i-1)%2][j][k][0]+f[(i-1)%2][j][k][1])%mod;
				}
				else
				{
    
    
					f[i%2][j][k][0]=(f[(i-1)%2][j][k][0]+f[(i-1)%2][j][k][1])%mod;
					f[i%2][j][k][1]=(f[(i-1)%2][j-1][k][1]+f[(i-1)%2][j-1][k-1][0]+f[(i-1)%2][j-1][k-1][1])%mod;
				}
			}
	printf("%lld",(f[n%2][m][s][0]+f[n%2][m][s][1])%mod);
}

猜你喜欢

转载自blog.csdn.net/weixin_46830417/article/details/112860893