题解 洛谷 P2679 【子串】
一道区间dp。
状态很好设,我们可以设 表示在 的第 位前取出 个子串与 的前 位一样的方案数。然后发现不是很好转移。
这个时候很容易就想到,我们再设一维0/1,即 ,表示 的第 位是否取到了。这样就可以分类讨论转移了。
因为我做的时候不会转移(太菜了)。 所以重点说转移。
首先,若 ,那么说明 的第 位不可能取到了,因此匹配不了, 肯定为 了。而 由于 的第 为不参与,那么肯定就等于到上一位的结果,即 。
接下来讨论 的情况。 显然和上面是一样的,即 。但是 怎么考虑呢?如果 的第 位是单独算的(即不和之前的一位组成子串),那方案数是 。就是到这一位不选,选 的子串(这好理解吧)。如果 的第 位不是单独算的,也就是说和之前的拼接起来,那么就是 的 位和 的 位一样才可以拼接,所以这里方案数是 。那么 方程就推出来了。
最后由于内存显然不够,每个之和 有关,滚动一下 数组就好。还有,初始化 ,否则就全是 啦。
写了这么多,感觉有点啰嗦,希望您能看得懂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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .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语句:使用策略模式优化代码结构