洛谷P2679 子串
因为该题需要求解方案数,因此我们不能用计数题的常用方法,即用递推来解决,类似于动态规划的思想。
我们用dp[i][j][h][o]表示第一个串枚举到了i,第二个串枚举到了j,A中取了h串,o表示选不选当前第i位的方案数。
可以得出以下的状态转移:
如果此位不选择的话
dp[i][j][h][0]=dp[i−1][j][h][0]+dp[i−1][j][h][1],此位不选则用加法原理选之前一位选择的和。
如果此位选择的话:
如果a[i]和b[j]不相等的话选择该位不能产生一个满足条件的子串。
如果相等的话,子串个数增加和不增加的情况都需要考虑,子串个数不增加的话,则i−1必须选,而选了i之后子串个数增加的话,i−1可选可不选。注意此时第二个串应该加上枚举到j−1的方案。
然后i的转移只跟i-1有关,因此考虑空间优化
#include <bits/stdc++.h>
#define N 1001001
#define mod 1000000007
using namespace std;
int n, m, k, dp[2][1001][1001][2];
char a[N], b[N];
void init()
{
scanf("%d%d%d", &n, &m, &k);
scanf("%s%s", a + 1, b + 1);
dp[0][0][0][0] = dp[1][0][0][0] = 1;
}
int add(int a, int b) {return (a + b) % mod;}
int main()
{
init();
for (int i = 1, now = 1; i <= n; i++, now ^= 1)
for (int j = 1; j <= m; j++)
for (int h = 1; h <= k; h++)
{
dp[now][j][h][0] = (dp[now ^ 1][j][h][1] + dp[now ^ 1][j][h][0]) % mod;//上一位
if (a[i] == b[j])
{
dp[now][j][h][1] = 0;
dp[now][j][h][1] = (dp[now][j][h][1] + dp[now ^ 1][j - 1][h][1]) % mod;
dp[now][j][h][1] = (dp[now][j][h][1] + dp[now ^ 1][j - 1][h - 1][1]) % mod;
dp[now][j][h][1] = (dp[now][j][h][1] + dp[now ^ 1][j - 1][h - 1][0]) % mod;
}
else dp[now][j][h][1] = 0;
}
printf("%d", (dp[n & 1][m][k][0] + dp[n & 1][m][k][1])% mod);//第一位判断是否是奇数或偶数,最后一位判断是否相等。
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· 官方的 MCP C# SDK:csharp-sdk
· 一款 .NET 开源、功能强大的远程连接管理工具,支持 RDP、VNC、SSH 等多种主流协议!
· 提示词工程师自白:我如何用一个技巧解放自己的生产力
· 一文搞懂MCP协议与Function Call的区别
· 如何不购买域名在云服务器上搭建HTTPS服务