CodeForces 808G Anthem of Berland 前缀函数 KMP DP
题意
第一行给我们一串长为s,只包含小写字母与问号的字符串A,第二行给我们一个长为t只有小写字母的字符串B, 同时满足 $ s * t \le 1e7 $
我们可以把问号变成任意的字母,我们需要求出如何变换才能使A串包含最多次B串(可以重叠),输出这个最大值
思路
单模式串匹配我们可以想到KMP算法或者前缀函数
一开始贪心考虑将“?”设置为100%匹配,但是显然这是行不通的,比如下面这组数据
acca
\]
显然答案是2,A应该变成如果kmp算法来贪心匹配,到第二个问号的时候,会将?设置为c,那么就和正确结果不符了
- 因为两字符串长度乘积最多为一千万,所以可以考虑DP,我们先预处理出B串的前缀函数值,然后给B串添加一个分隔符#之后,处理出前缀函数的自动机
\]
也就是在当前前缀函数值为i的情况下,下一个字符为j时转移到的前缀函数值。
- 这样我们设置DP数组
\]
为当前在A串的i位置,匹配到B串的j位置时(也就是前缀函数为j)的最大匹配数。为了便于理解我们初始化dp[0][0]为0,其他值为-1,转移方程为
\\
dp[i][prem[j][A[i]]] = max_{0 \le j \le t}\{dp[i - 1][j] + (prem[j][A[i]] == t)\} (A[i] \ne '?')
\]
- 最后取dp[s][i]中的最大值即可,对于空间问题,可以将两维写在一维中,或者使用滚动数组
AC代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100000;
char ss[N + 5], sss[N + 5];
int prem[N + 5][26];
int pf[N + 5];
int dp[2][N + 5];
int len;
void prefun(char *s)
{
len = strlen(s + 1);
pf[0] = pf[1] = 0;
for (int i = 2; i <= len; ++i)
{
pf[i] = 0;
int l = pf[i - 1];
while (l && s[l + 1] != s[i])
{
l = pf[l];
}
if (s[l + 1] == s[i])
{
pf[i] = l + 1;
}
}
}
void preatm(char *s)
{
s[++len] = '#';
for (int i = 0; i < len; ++i)
{
for (int j = 0; j < 26; ++j)
{
if (i && 'a' + j != s[i + 1])
{
prem[i][j] = prem[pf[i]][j];
}
else
{
prem[i][j] = i + ('a' + j == s[i + 1]);
}
}
}
}
int main()
{
scanf("%s%s", ss + 1, sss + 1);
memset(dp, -1, sizeof(dp));
prefun(sss);
preatm(sss);
dp[0][0] = 0;
int len2 = strlen(ss + 1);
for (int i = 1; ss[i]; ++i)
{
if (ss[i] == '?')
{
for (int j = 0; j < len; ++j)
{
if (dp[1 - i % 2][j] != -1)
{
for (int k = 0; k < 26; ++k)
{
dp[i % 2][prem[j][k]] = max(dp[1 - i % 2][j] + (prem[j][k] == len - 1), dp[i % 2][prem[j][k]]);
}
}
}
}
else
{
for (int j = 0; j < len; ++j)
{
if (dp[1 - i % 2][j] != -1)
{
dp[i % 2][prem[j][ss[i] - 'a']] = max(dp[1 - i % 2][j] + (prem[j][ss[i] - 'a'] == len - 1), dp[i % 2][prem[j][ss[i] - 'a']]);
}
}
}
for (int j = 0; j < len; ++j)
{
dp[1 - i % 2][j] = -1;
}
}
int ans = 0;
for (int i = 0; i < len; ++i)
{
ans = max(ans, dp[len2 % 2][i]);
}
printf("%d\n", ans);
return 0;
}
CodeForces 808G Anthem of Berland 前缀函数 KMP DP的更多相关文章
- codeforces 808G Anthem of Berland
codeforces 808G Anthem of Berland 题面 给定\(s\)串和\(t\)串,字符集是小写字母.\(s\)串中有些位置的值不确定,要求你确定这些位置上的值,使得\(t\)在 ...
- Codeforces 808G Anthem of Berland - KMP - 动态规划
题目传送门 传送点I 传送点II 传送点III 题目大意 给定一个字符串$s$,和一个字符串$t$,$t$只包含小写字母,$s$包含小写字母和通配符'?'.询问$t$可能在$s$中出现最多多少次. 原 ...
- Codeforces 808G Anthem of Berland【KMP】【DP】
LINK 简要题意 给你一个串s,上面有字母和一些通配符,问你将通配符换成字母之后最多可以出现多少次串t 首先有一个很傻子的做法就是\(dp_{i,j}\)表示s到第i个位置匹配t串前j个字符的完整t ...
- Codeforces 808G Anthem of Berland(KMP+基础DP)
题意 给定一个字符串 \(s\) ,一个字符串 \(t\) ,其中 \(s\) 包含小写字母和 "?" ,\(t\) 只包含小写字母,现在把 \(s\) 中的问号替换成任意的小写字 ...
- 2021.08.30 前缀函数和KMP
2021.08.30 前缀函数和KMP KMP算法详解-彻底清楚了(转载+部分原创) - sofu6 - 博客园 (cnblogs.com) KMP算法next数组的一种理解思路 - 挠到头秃 - 博 ...
- 前缀函数与Z函数介绍
字符串算法果然玄学=_= 参考资料: OI Wiki:前缀函数与KMP算法 OI Wiki:Z函数(扩展KMP) 0. 约定 字符串的下标从 \(0\) 开始.\(|s|\) 表示字符串 \(s\) ...
- 转载 - kmp next函数 kmp的周期问题,深入了解kmp中next的原理
出处:http://www.cnblogs.com/wuyiqi/archive/2012/01/06/2314078.html kmp next函数 kmp的周期问题,深入了解kmp中next的原理 ...
- POJ 3336 Count the string (KMP+DP,好题)
参考连接: KMP+DP: http://www.cnblogs.com/yuelingzhi/archive/2011/08/03/2126346.html 另外给出一个没用dp做的:http:// ...
- 【KMP+DP】Count the string
KMP算法的综合练习 DP很久没写搞了半天才明白.本题结合Next[]的意义以及动态规划考察对KMP算法的掌握. Problem Description It is well known that A ...
- codeforces432D Prefixes and Suffixes(kmp+dp)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud D. Prefixes and Suffixes You have a strin ...
随机推荐
- 文本编辑器vi使用命令
使用对象: 用于编辑任何ASCII文本,对于编辑源程序尤其有用.可以对文本进行创建]查找.替换.删除.复制和粘贴等操作. 三种工作模式 命令模式:进入vi编辑器默认处于命令模式.命令模式下控制屏幕光标 ...
- 从内核世界透视 mmap 内存映射的本质(源码实现篇)
本文基于内核 5.4 版本源码讨论 通过上篇文章 <从内核世界透视 mmap 内存映射的本质(原理篇)>的介绍,我们现在已经非常清楚了 mmap 背后的映射原理以及它的使用方法,其核心就是 ...
- Trino容错模式深度测评与思考
本文分享自华为云社区<走向批处理-交互式分析一体化: Trino容错模式深度测评与思考>,作者:HetuEngine九级代言 . 本文系华为云大数据研发团队原创,原创作者:文博,梦月 1 ...
- 文心一言 VS 讯飞星火 VS chatgpt (115)-- 算法导论10.2 8题
八.用go语言,说明如何在每个元素仅使用一个指针 x.np(而不是通常的两个指针 next和prev)的下实现双向链表.假设所有指针的值都可视为 k 位的整型数,且定义x.np=x.next XOR ...
- Hall定理(霍尔定理)证明及推广
引言 网络上有许多Hall定理的证明,但是对于Hall定理的几个推广的介绍却少之又少,因此本文来简单介绍一下 注:为了使这篇文章看起来简单易懂,本文将不会使用图论语言,会图论的朋友们可以自行翻译为图论 ...
- 关于通过StringTemplate模板生成xml转成excel后office无法打开的问题解决
说明:本人最近在着手实现导出日志数据,由于日志数据过多,在网上查找java 导出大量数据到excel的例子. 后发现园子里某位老哥通过StringTemplate模板生成excel格式的xml,这个思 ...
- 把 map 中的 key 由驼峰命名转为下划线
import cn.hutool.core.util.StrUtil; /** * 把 map 中的 key 由驼峰命名转为下划线 */public HashMap<String, Object ...
- 【行云流水线实践】基于“OneBuild”方法对镜像进行快速装箱
在云原生领域,无论使用哪种编排调度平台,Kubernetes,DockerSwarm,OpenShift等,业务都需要基于镜像进行交付,我们在内部实践"Source-to-image&quo ...
- Eclipse设置GC日志输出
今天看了关于垃圾回收的书籍,然后自己就想自己试试,自己就在eclipse里面配置了日志输出.方法如下: 1 右键项目,选择properties 2 选择run/debug setting 新建一个a ...
- 解决IDEA中.properties文件中文变问号(???)的问题(已解决)
问题背景 构建SpringBoot项目时,项目结构中有一个application.properties文件.这个项目是Spring Boot一个特有的配置文件.内容如下(我写了一些日志的配置): 写到 ...