洛谷 P2679 子串 题解

P2679 子串

题目描述

首先设f[i][j][p]表示在(A)串中选(i)个字符被划分为(k)段匹配(B)串中的(j)个字符方案数,但是发现还不够,因为当前选还是不选的(k)转移取决于上个字符选没有选没。所以我们再设一维状态(0/1)表示当前字符选或者不选的方案数。

转移:1.如果a[i]==b[j]

f[i][j][p][0]=f[i-1][j][p][0]+f[i-1][j][p][1];
这一位不拿,不累加j-1的合法状态
f[i][j][p][1]=f[i-1][j-1][p][0]+f[i-1][j-1][p-1][1]+f[i-1][j-1][p][1];
f[i-1][j-1][p][0] 最后一位不匹配,必须重新划分区间,必须从p中转,不累加p-1的合法状态
f[i-1][j-1][p-1][1] 最后一位匹配,但不重新划分区间,必须从p-1中转,累加p-1的合法状态
f[i-1][j-1][p][1]  最后一位匹配,重新划分一个区间,p不变,直接中转

2.如果a[i]!=b[j]

f[i][j][p][0]=f[i-1][j][p][0]+f[i-1][j][p][1];
同上
f[i][j][p][1]=0 因为字符不同无法匹配,所以直接为0

初始化

    for (int i=0;i<=n;i++)
    f[i][0][0][0]=f[i][0][0][1]=1;
    不管i选几个让B串中匹配的数为0的只有一种,就是什么都不选
    f[0][0][0][0]和f[0][0][0][1]也要初始化,因为中转要用到

70分

#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const int N=510,M=51,mod=1e9+7;
char a[N],b[M];
int f[N][M][M][2];
int n,m,k;
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    scanf("%s%s",a+1,b+1);
    for (int i=0;i<=n;i++)
    f[i][0][0][0]=1;
    for (int i=1;i<=n;i++)
 	for (int j=1;j<=m;j++)
    for (int p=1;p<=k;p++)
    if (a[i]==b[j])
    {
        f[i][j][p][0]=((ll)f[i-1][j][p][0]+f[i-1][j][p][1])%mod;
        f[i][j][p][1]=((ll)f[i-1][j-1][p][1]+f[i-1][j-1][p-1][0]+f[i-1][j-1][p-1][1])%mod;
    }
    else
    {
        f[i][j][p][0]=((ll)f[i-1][j][p][0]+f[i-1][j][p][1])%mod;
        f[i][j][p][1]=0;
    }
    printf("%d
",(f[n][m][k][1]+f[n][m][k][0])%mod);
    return 0;
}

因为数据比较大,直接(DP)(MLE),但是我们观察发现,每次中转只用到i-1和i,所以我们用滚动数组来代替第一维

初始设now=1,因为1对xor运算无影响

now1就相当于i-1,因为11=0,0^1=1,所以实现了数组的滚动。

最后输出n^1,如果n是单数,肯定滚动到1,偶数滚动到0,所以判断奇偶。

100分

#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const int N=1010,M=210,mod=1e9+7;
char a[N],b[M];
int f[2][M][M][2];
int n,m,k;
bool now=1;
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	scanf("%s%s",a+1,b+1);
	f[0][0][0][0]=f[1][0][0][0]=1;
	now=1;
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)
		for (int p=1;p<=k;p++)
		if (a[i]==b[j])
		{
			f[now][j][p][0]=((ll)f[now^1][j][p][0]+f[now^1][j][p][1])%mod;
			f[now][j][p][1]=((ll)f[now^1][j-1][p][1]+f[now^1][j-1][p-1][0]+f[now^1][j-1][p-1][1])%mod;
		}
		else
		{
			f[now][j][p][0]=((ll)f[now^1][j][p][0]+f[now^1][j][p][1])%mod;
			f[now][j][p][1]=0;
		}
		now^=1;
	}
	printf("%d
",(f[n&1][m][k][1]+f[n&1][m][k][0])%mod);
	return 0;
}
原文地址:https://www.cnblogs.com/last-diary/p/10806678.html