线性dp:P2679 子串

本文讨论了一道名为P2679的编程题,涉及公共子串问题的变种。作者通过模拟和代码实现解释了如何解决此问题,特别强调了定住b串找a串的策略和优化技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.P2679 子串

传送门icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P2679这道题是公共子串问题的变种,但是我第一时间确实没想到转移方程(写少了)

一开始看了题解也没太看懂,直到自己模拟一遍(模拟数据便于理解原理)下面是感悟

这道题我最初的疑惑点在于究竟是定住a串找b串,还是定住b串找a串。我在一开始的想法是定住b串找a串,因为这道题我们想要用a串中的子串来匹配b串。但是后来我发现这不可行,因为a串只能按照顺序来找,如果定住b串,就不能保证后面补充的是从前面来的了,如此一来并不好操作(子串间连接顺序不同)。

这里还用到了一个优化,把第一维a串的遍历省掉了,因为每一次只与前一个位置的有关

下面直接用代码来解释(有注释)

Welcome - Luogu Spilopelia 配合这个食用

图摘自https://www.luogu.com.cn/article/k0zkdin9

// Problem: 
//     P2679 [NOIP2015 提高组] 子串
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2679
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
using namespace std;
int f[2][205][205][2];//这个和上一个  / 匹配的m / 多少个子串 / 用或者不用这个a[i]
char a[1005],b[205];
const int P=1000000007;

int main(){
	int n,m,k;
	cin>>n>>m>>k;
	cin>>(a+1)>>(b+1);
    f[0][0][0][0]=1;
    f[1][0][0][0]=1;  //不用a[i]满足0个b对应x个a的情况(0<=x<=n)这里x被简化成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%2][j][p][1]=((f[(i-1)%2][j-1][p][1]+f[(i-1)%2][j-1][p-1][1])%P+f[(i-1)%2][j-1][p-1][0]%P)%P;
					f[i%2][j][p][0]=(f[(i-1)%2][j][p][0]+f[(i-1)%2][j][p][1])%P;
				}
				else{
					f[i%2][j][p][1]=0;
					f[i%2][j][p][0]=(f[(i-1)%2][j][p][0]+f[(i-1)%2][j][p][1])%P;
                    //用这里收割从前面来的子串
				}
			}
		}
	}
	cout<<(f[n%2][m][k][0]+f[n%2][m][k][1])%P;
	
	
	
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值