【字符串】manacher算法
Definition
定义一个回文串为从字符串两侧向中心扫描时,左右指针指向得字符始终相同的字符串。
使用manacher算法可以在线性时间内求解出一个字符串的最长回文子串。
Solution
考虑回文串有两种:第一种对称轴在两字符之间,另一种对称轴在一个字符中心。这样分情况讨论十分不方便,我们使用一种奇技淫巧将之统一成长度为奇数的回文串,即对称轴在字符中心:将原串每两个字符之间都添加一个相同的、不在原串中的字符。显然长度为偶数的回文串对称轴会在添加的字符上,问题就得到了解决。例如:
接着发现一个回文半径为len的新串,对应老串的回文长度为len-1。证明可以根据老串的对称中心分类讨论。
于是对于每一个回文中心记录一个len作为新串的以它为中心的回文子串长度,问题就转化为了求len数组。
接着继续分类讨论:
我们从左向右扫描数组,扫描到\(i\)时,\(\forall~j~<~i\),\(len_j\)都已经被算出来了。
我们设一个辅助变量pos为当前所有回文子串中,右端点最靠右的回文子串的右端点位置,然后对每个pos记录它是哪个回文中心延伸而成的,即为pre。下面可以分两种情况讨论:
一、\(i~\leq~pos\)
这种情况下,\(i\)一定在pos所在的回文串内部,我们找到\(i\)关于\(pre_{pos}\)的对称点\(j\),再次分两种情况讨论:
1、1 \(len_j~<~pos~-~i\)
这也就说明以\(j\)为回文中心的回文子串是大回文子串的子串,因为\(i\)也属于大回文子串,所以\(j\)所在的回文子串也是关于\(pre_{pos}\)对称的,于是显然有\(len_i~=~len_j\)
1、2 \(len_j~\geq~pos~-~i\)
这说明以\(j\)为中心的回文子串不是大回文子串的内部,但是一直到大回文子串的边界它的回文性质都是成立的,因为对称性,所以\(i~\sim~pos\)的回文性质都是成立的,于是可以从\(pos~+~1\)开始暴力判断。
二、\(i~>~pos\)
这种情况下,没有能与\(i\)对称的位置,直接暴力向后扫描。
考虑复杂度:
发现每次暴力判断,pos一定会增加,于是最多暴力判断\(O(n)\)次。剩下的操作都是\(O(1)\)。于是复杂度为\(O(n)\)
Example
Description
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
Input
一行一个字符串
Output
一行一个数表示答案
Hint
长度小于1.1e8,保证数据合法。
Solution
板子题要啥solution
Code
#include <cstdio>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long
typedef long long int ll;
namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
}
template <typename T>
inline void qr(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
}
template <typename T>
inline void ReadDb(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if (ch == '.') {
ch = IPT::GetChar();
double base = 1;
while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if (lst == '-') x = -x;
}
namespace OPT {
char buf[120];
}
template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
rg int top=0;
do {OPT::buf[++top] = x % 10 + '0';} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
}
const int maxn = 22000010;
char MU[maxn], temp[maxn];
int lenth[maxn], pre[maxn], pos;
int main() {
freopen("1.in", "r", stdin);
int len = 0;
while(~(MU[++len] = IPT::GetChar()));
MU[len--] = '\0';
temp[0] = '$';
for (rg int i = 1; i <= len; ++i) temp[(i << 1) - 1] = '$' , temp[i << 1] = MU[i];
temp[len = (len << 1) + 1] = '$';
for (rg int i = 1; i <= len; ++i) {
if (i <= pos) {
int mid = pre[pos], j = (mid << 1) - i;
if (lenth[j] < (pos - i)) lenth[i] = lenth[j];
else {
j = (i << 1) - pos;
while(temp[j] == temp[pos]) ++pos,--j;
pre[--pos] = i; lenth[i] = pos - i + 1;
}
} else {
pos = i; int j = i;
while(temp[j] == temp[pos]) ++pos,--j;
pre[--pos] = i; lenth[i] = pos - i + 1;
}
}
int ans = 0;
for (rg int i = 1; i <= len; ++i) {
ans = std::max(ans, lenth[i]);
}
qw(ans - 1, '\n', true);
return 0;
}
Summary
我可总算把智推两个月的manecher学完了……
【字符串】manacher算法的更多相关文章
- 第5题 查找字符串中的最长回文字符串---Manacher算法
转载:https://www.felix021.com/blog/read.php?2040 首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一 ...
- POJ 3974 Palindrome 字符串 Manacher算法
http://poj.org/problem?id=3974 模板题,Manacher算法主要利用了已匹配回文串的对称性,对前面已匹配的回文串进行利用,使时间复杂度从O(n^2)变为O(n). htt ...
- 最长回文字符串(manacher算法)
偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid. 题目描述: 回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串. ...
- 【转载】最长回文字符串(manacher算法)
原文转载自:http://blog.csdn.net/lsjseu/article/details/9990539 偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid ...
- 利用Manacher算法寻找字符串中的最长回文序列(palindrome)
寻找字符串中的最长回文序列和所有回文序列(正向和反向一样的序列,如aba,abba等)算是挺早以前提出的算法问题了,最近再刷Leetcode算法题的时候遇到了一个(题目),所以就顺便写下. 如果用正反 ...
- 计算字符串的最长回文子串 :Manacher算法介绍
转自: http://www.open-open.com/lib/view/open1419150233417.html Manacher算法 在介绍算法之前,首先介绍一下什么是回文串,所谓回文串,简 ...
- 算法进阶面试题01——KMP算法详解、输出含两次原子串的最短串、判断T1是否包含T2子树、Manacher算法详解、使字符串成为最短回文串
1.KMP算法详解与应用 子序列:可以连续可以不连续. 子数组/串:要连续 暴力方法:逐个位置比对. KMP:让前面的,指导后面. 概念建设: d的最长前缀与最长后缀的匹配长度为3.(前缀不能到最后一 ...
- 【字符串算法2】浅谈Manacher算法
[字符串算法1] 字符串Hash(优雅的暴力) [字符串算法2]Manacher算法 [字符串算法3]KMP算法 这里将讲述 字符串算法2:Manacher算法 问题:给出字符串S(限制见后)求出最 ...
- ACM -- 算法小结(八)字符串算法之Manacher算法
字符串算法 -- Manacher算法 首先介绍基础入门知识,以下这部分来着一贴吧,由于是很久之前看的,最近才整理一下,发现没有保存链接,请原创楼主见谅. //首先:大家都知道什么叫回文串吧,这个算法 ...
随机推荐
- TPO-17 C1 Find materials for an opera paper
TPO-17 C1 Find materials for an opera paper production n. 成果:产品:生产:作品 第 1 段 1.Listen to a conversati ...
- NO.08--VUE之自定义组件添加原生事件
前几篇给大家分享了我的业余的“薅羊毛”的经历,回归正题,讲回vue吧: 许多vue新手在工作开发中会遇到一个问题,直接使用 button 添加原生事件是没有问题的,但是使用自定义组件添加原生事件时,就 ...
- java之接口开发-初级篇-http和https
http协议util address(url地址),str(数据参数) private static HttpMethod getPostJsonMethodInRequestBody(String ...
- gets函数的完美替代
众所周知 在C语言中scanf用来读取一行字符串时遇到空格或回车会停止 而若要读入一行带空格的字符串时 有些人会用gets来代替 然而,gets的最大问题在于:会读取超过数组长度上限个字符,而超出长度 ...
- python3【基础】-list&tuple
一.list概述 list (列表)是python中最常用的数据类型之一,通过列表可以对数据实现最方便的存储,修改等操作.在python3中,list支持如下方法: Help on class lis ...
- Beta发布——视频博客
1.视频链接 视频上传至优酷自频道,地址链接:http://v.youku.com/v_show/id_XMzkzNzAxNDk2OA==.html?spm=a2hzp.8244740.0.0 2.视 ...
- PSP Daily软件Alpha版本——基于NABCD评论,及改进建议
1.根据(不限于)NABCD评论作品的选题: 此软件的用户人群较为明确,即:用户(软件工程课上学生)记录例行报告.写每周PSP表格和统计的需求.潜在用户还有未来该课堂的学生和需要用PSP方法记录任务完 ...
- c语言基础笔记
一 :数据类型 1.float类型,在输出的时候可以使用 .数字 来把浮点数精确到小数点后几位,比如 printf("%.3f",float)精确到小数点后三位,不足补0 2.字 ...
- 一个form表单,多个提交按钮
技巧就是把提交的input的类型改成button!这样就可以实现多个按钮提交! 以下是案例: <form action="" id="tijiao"> ...
- JSON字符串转换成对象时候 需要有默认构造器 因为这是通过反射创建的 反射是先通过默认构造器创建对象的
JSON字符串转换成对象时候 需要有默认构造器 因为这是通过反射创建的 反射是先通过默认构造器创建对象的