题解 洛谷 P2679 【子串】

一道区间dp。

状态很好设,我们可以设 dp(i,j,k) 表示在 a 的第 i 位前取出 k 个子串与 b 的前 j 位一样的方案数。然后发现不是很好转移。

这个时候很容易就想到,我们再设一维0/1,即 dp(i,j,k,t)t表示 a 的第 i 位是否取到了。这样就可以分类讨论转移了。

因为我做的时候不会转移(太菜了)。 所以重点说转移。

首先,若 ai!=bj,那么说明 a 的第 i 位不可能取到了,因此匹配不了,dp(i,j,k,1) 肯定为 0 了。而 dp(i,j,k,0) 由于 a 的第 i 为不参与,那么肯定就等于到上一位的结果,即 dp(i1,j,k,0)+dp(i1,j,k,1)

接下来讨论 ai=bj 的情况。dp(i,j,k,0) 显然和上面是一样的,即 dp(i1,j,k,0)+dp(i1,j,k,1)。但是 dp(i,j,k,1) 怎么考虑呢?如果 a 的第 i 位是单独算的(即不和之前的一位组成子串),那方案数是 dp(i,j1,k1,0)。就是到这一位不选,选 k1 的子串(这好理解吧)。如果 a 的第 i 位不是单独算的,也就是说和之前的拼接起来,那么就是 ai1 位和 bj1 位一样才可以拼接,所以这里方案数是 dp(i1,j1,k,1)。那么 dp 方程就推出来了。

最后由于内存显然不够,每个之和 i1 有关,滚动一下 dp 数组就好。还有,初始化 dp(i,0,0,0)=1,否则就全是 0 啦。

写了这么多,感觉有点啰嗦,希望您能看得懂qwq。最后贴个代码。

#include<bits/stdc++.h>
using namespace std;
int n,m,K;
char a[1201],b[1201]; 
int mod=1000000007;
long long f[2][201][201][2];
int main()
{
	cin >> n >> m >> K;
	for (int i=1;i<=n;i++) cin >> a[i];
	for (int i=1;i<=m;i++) cin >> b[i];
	f[0][0][0][0]=1;
	for (int i=1;i<=n;i++)
	{
		f[i%2][0][0][0]=1;
		for (int j=1;j<=m;j++)
		{
			for (int k=1;k<=min(j,K);k++)
			{
				if (a[i]!=b[j])
				{
					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]=0;
				}
				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%2][j-1][k-1][0]+f[(i-1)%2][j-1][k][1])%mod;
				}
			}
		}
	}
	cout << ((f[n%2][m][K][0]+f[n%2][m][K][1])%mod) << endl;
	return 0;
}
posted @   Little09  阅读(133)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示