ABB:KMP 的做法非常巧妙。

哈希

思路

显然正着做一遍哈希,倒着做一遍哈希,然后枚举回文中心即可。

时间复杂度 \(O(n)\)。

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pi;
const int N=400005;
const ull base=13331;
ull phash[N],shash[N],pw[N];
int n,ans;
char s[N];
void dohash()
{
pw[0]=1;
for(int i=1;i<N;i++)pw[i]=pw[i-1]*base;
for(int i=1;i<=n;i++)phash[i]=phash[i-1]*base+s[i];
for(int i=n;i>=1;i--)shash[i]=shash[i+1]*base+s[i];
}
ull gethash(int op,int l,int r)
{
if(op==0)return (phash[r]-phash[l-1]*pw[r-l+1]);
return (shash[l]-shash[r+1]*pw[r-l+1]);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>s+1;
ans=n-1;
if(n==1)
{
cout<<0;
return 0;
}
dohash();
for(int i=1;i<=n;i++)
{
if(i-1>=n-(i+1)+1)
{
int len=n-(i+1)+1;
if(gethash(0,i-1-len+1,i-1)==gethash(1,i+1,i+1+len-1))
{
ans=min(ans,i-1-len);
}
}
if(i>=n-(i+1)+1)
{
int len=n-(i+1)+1;
if(gethash(0,i-len+1,i)==gethash(1,i+1,i+1+len-1))
{
ans=min(ans,i-len);
}
}
}
cout<<ans;
return 0;
}

哈希的代码又臭又长,肯定不是这题的最优解。

KMP

思路

我们考虑这题要求的本质是什么,显然是求字符串 \(s\) 最长的回文后缀的长度 \(l\),那么答案就是 \(n-l\)。因为剩下的那些必须对称过去。

那么如何求最长的回文后缀呢?我们可以先把字符串 \(s\) 反转为 \(s'\),把后缀转化为前缀便于处理。

由于回文串正着读和反着读都一样,可以发现回文后缀满足是字符串 \(s'\) 的一段前缀,也是字符串 \(s\) 的一段后缀。

因此如果字符串 \(s'\) 的一段前缀与字符串 \(s\) 的一段后缀相等,就说明这是一个合法的回文后缀。

如果要让这个后缀最长,那么显然是 KMP 的 \(next_n\),就求出来了。

实现上,我们可以将最后的主串设置为 \(s'\) 与任意一个分隔符与 \(s\) 拼接起来的字符串,然后做一遍 KMP 即可。

时间复杂度 \(O(n)\)。

代码

非常简短,注意字符串开两倍的长度。

#include <bits/stdc++.h>
using namespace std;
const int N=800005;
int n,ne[N];
char s[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>s+n+2;
s[n+1]='%';
for(int i=1,j=2*n+1;i<=n;i++,j--)s[i]=s[j];
int now=0;
for(int i=2;i<=2*n+1;i++)
{
while(now&&s[now+1]!=s[i])now=ne[now];
if(s[now+1]==s[i])now++;
ne[i]=now;
}
cout<<n-ne[2*n+1];
return 0;
}

Luogu P9606 CERC2019 ABB 题解 [ 绿 ] [ KMP ] [ 字符串哈希 ]的更多相关文章

  1. UVA - 11475 Extend to Palindrome —— 字符串哈希 or KMP or 后缀数组

    题目链接:https://vjudge.net/problem/UVA-11475 题意: 给出一个字符串,问在该字符串后面至少添加几个字符,使得其成为回文串,并输出该回文串. 题解: 实际上是求该字 ...

  2. 洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速$dp\&Floyd$)

    洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速\(dp\&Floyd\)) 标签:题解 阅读体验:https://zybuluo.com/Junl ...

  3. KMP字符串模式匹配详解(转)

    来自CSDN     A_B_C_ABC 网友 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n);KMP匹配算法.可以证明它的时间复杂度 ...

  4. 字符串哈希及KMP

    字符串很神奇,因为它在计算机中应用很广泛,就每一个程序都需要用到字符串,所以学好字符串是非常重要的. 接下来就介绍两个字符串的基本操作 1:字符串hash  一种可以查找几个字符串有几个不同的字符串. ...

  5. BM和KMP字符串匹配算法学习

    BM和KMP字符串匹配算法学习 分类: 研究与学习 字符串匹配BM(Boyer-Moore)算法学习心得 http://www.cnblogs.com/a180285/archive/2011/12/ ...

  6. KMP字符串模式匹配详解(zz)

    刚看到位兄弟也贴了份KMP算法说明,但本人觉得说的不是很详细,当初我在看这个算法的时候也看的头晕昏昏的,我贴的这份也是网上找的.且听详细分解: KMP字符串模式匹配详解 来自CSDN     A_B_ ...

  7. KMP字符串模式匹配详解

    KMP字符串模式匹配详解 http://www.cppblog.com/oosky/archive/2006/07/06/9486.html

  8. Luogu P4503 [CTSC2014]企鹅QQ(字符串哈希)

    P4503 [CTSC2014]企鹅QQ 题面 题目背景 \(PenguinQQ\) 是中国最大.最具影响力的 \(SNS(Social Networking Services)\) 网站,以实名制为 ...

  9. HDU 1880 题解(字符串哈希)

    题面: 魔咒词典 Time Limit: 8000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  10. 【CodeForces】961 F. k-substrings 字符串哈希+二分

    [题目]F. k-substrings [题意]给定长度为n的串S,对于S的每个k-子串$s_ks_{k+1}...s_{n-k+1},k\in[1,\left \lceil \frac{n}{2} ...

随机推荐

  1. k8s之集群部署(kubeadm)

    [master&node] 1.修改主机名 hostnamectl set-hostname master-01 cat >> /etc/hosts << EOF 17 ...

  2. golang之常用命令

    golang常用操作与命令 1.执行golang文件 go run hello_world.go 2.编译成可执行文件(交叉编译) go build hello_world 则会生成hello_wor ...

  3. 设计模式【3.3】-- CGLIB动态代理源码解读

    cglib 动态代理 cglib介绍 CGLIB 是一个开源项目,一个强大高性能高质量的代码生成库,可以在运行期拓展 Java 类,实现 Java 接口等等.底层是使用一个小而快的字节码处理框架 AS ...

  4. 交易系统:电商、O2O、线下门店购物流程详解

    大家好,我是汤师爷~ 新零售业务涉及多个销售渠道,每个渠道都有其独特的业务特点,需要相应的营销方式.运营策略和供应链管理. 主要销售渠道包括:实体门店(包括直营连锁店.加盟门店).电商平台销售(如淘宝 ...

  5. C#实现控制台显示动态进度条百分比

    C#实现控制台显示动态进度条 前言 private static void Main(string[] args) { bool isBreak = false; ConsoleColor color ...

  6. 了解URLSearchParams对象

    URLSearchParams对象用于处理URL中查询字符串,即?之后的部分. 1.语法 其实例对象的用法和Set数据结构类似.实例对象本身是可遍历对象.但是不是遍历器. var paramsStri ...

  7. 痞子衡嵌入式:MCUXpresso IDE下C++源文件中嵌套定义的复合数据类型命名空间认定

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下C++源文件中嵌套定义的复合数据类型命名空间认定. 痞子衡之前写过一篇文章 <MCUXpresso ...

  8. GitHub Workflow 和 Action 的一些注意事项

    GitHub 的 workflow 和 action 存在一些注意事项,总结如下,以供参考 Workflow on.issues.types 如果需要判断 label,不需要指定 opened,只需要 ...

  9. 在 Ubuntu 或 Debian 上安装 LaTeX

    在 Ubuntu 或 Debian 上安装 LaTeX LaTeX 是一种文档标记语言.建议使用 LaTeX 创建技术或科学文章.论文.报告.书籍和其他文档,如博士. 1. 打开你的终端 终端是一个命 ...

  10. 禁用Windows服务器iis错误导致启动vs调试

    问题描述: IIS站点错误会导致windows服务器启动vs调试,这在生产服务器是完全没必要的,会导致下面的问题,弹出一个调试框,必须手动关闭.很是不爽.. 关闭调试导入注册表: Windows Re ...