目录

Manacher算法 可在 \(O(n)\)的时间内求出一个字符串以每个位置为中心的最长回文子串。

原理:根据之前预处理出的回文串长度求得新的回文串长度

我们可以通过在字符中加上'#'来避免长度为偶数回文串没有中心的问题

原串 = "abcd"; 变为
新串 = "#a#b#c#d#";
原串中长度为奇数和偶数的回文串的长度均变为奇数,且原串中回文串的长度为新串回文串半径减一。

设置两个状态 $\max $ 和 \(p\) , \(p\) 表示当前已找到的回文串中,向右延伸最远的中心位置,$\max $ 表示其右端点。

设 \(r(i)\) 表示(新串中)第 \(i\) 个位置的回文半径(回文串长度的一半,包括第 \(i\) 个字符)按从左到右的顺序求解,枚举到第 \(i\) 个字符时,分三种情况考虑:

设\(\ j\) 为\(\ i\) 关于 \(p\) 的对称点,即 \(j = 2p - i\)

\(\max < i​\),即向右延伸最远的回文子串(黑色)没有覆盖 \(i​\),此时只有 \(r(i) \geq 1​\)。

\(\max \geq i\) 且 \(\max - i \geq r(j)\),即向右延伸最远的回文子串(黑色)覆盖了 \(i\),并且以 jj 为中心的最长回文子串完全与以 \(i\) 为中心的最长回文子串对称(蓝色),此时一定有 \(r(i) = r(j)\),即 \(r(i) \geq r(j)\)。

\(\max \geq i\) 且 \(\max - i \geq r(j)\),即向右延伸最远的回文子串(黑色)覆盖了 \(i\),但没有覆盖以 jj 为中心的最长回文子串的对称位置串,所以 \(r(i)\) 只能取被覆盖的(黄色)一部分,即 \(r(i) \geq \max - i\)。

code(伪)

int len;
void prepare(){
len = 0;
s2[++len] = '%';
for(int i = 0; i < s.size(); i++){
s2[++len] = '#';
s2[++len] = s[i];
}
s2[++len] = '#';
}
void manacher(){
int mid = 0, rb = 0;
//此处的rb是 真实值加一
//回文串为(lb, rb) (lb, mid] = [mid, rb) 所以计算半径直接rb - mid;
//因为每次扩展x相当于扩展rb, rb最多扩展n次, 所以O(N);
for(int i = 1; i <= len; i++) {
int x;
if(rb < i) x = 1;
else x = min(p[2*mid - i], rb - i); while(s2[i+x] == s2[i-x]) x++; if(i > rb) mid = i, rb = i+x;
p[i] = x;
}
} ans = max(p[]) - 1;
//原串回文串长度等于新串回文半径减一.

Manacher学习笔记的更多相关文章

  1. Manacher 学习笔记

    \(\\\) \(Manacher\) 一种常用的字符串算法,用于处理一些回文字符相关的问题. 回文串:从前向后和从后向前输出一致. 回文中心:以这里开始,每次向外左右各扩展一个字符得到的回文串的中心 ...

  2. Manacher算法学习笔记 | LeetCode#5

    Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...

  3. 学习笔记 - Manacher算法

    Manacher算法 - 学习笔记 是从最近Codeforces的一场比赛了解到这个算法的~ 非常新奇,毕竟是第一次听说 \(O(n)\) 的回文串算法 我在 vjudge 上开了一个[练习],有兴趣 ...

  4. 【学习笔记】字符串—马拉车(Manacher)

    [学习笔记]字符串-马拉车(Manacher) 一:[前言] 马拉车用于求解连续回文子串问题,效率极高. 其核心思想与 \(kmp\) 类似:继承. --引自 \(yyx\) 学姐 二:[算法原理] ...

  5. OI知识点|NOIP考点|省选考点|教程与学习笔记合集

    点亮技能树行动-- 本篇blog按照分类将网上写的OI知识点归纳了一下,然后会附上蒟蒻我的学习笔记或者是我认为写的不错的专题博客qwqwqwq(好吧,其实已经咕咕咕了...) 基础算法 贪心 枚举 分 ...

  6. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  7. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  8. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  9. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

随机推荐

  1. poj2942 求v-DCC,二分图判奇环,补图

    /* 给定一张无向图,求有多少点不被任何奇环包含 推论1:如果两个点属于两个不同的v-DCC,则他们不可能在同一个奇环内 推论2:某个v-DCC中有奇环,则这个v-DCC中所有点必定被属于某个奇环 只 ...

  2. poj3162 树形dp|树的直径 + 双单调队列|线段树,好题啊

    题解链接:https://blog.csdn.net/shiqi_614/article/details/8105149 用树形dp是超时的,, /* 先求出每个点可以跑的最长距离dp[i][0|1] ...

  3. 基础运算符补充,流程控制之if判断/while循环

    常量 常量即指不变的量.在python中没有一个专门 的语法代表常量,程序员约定俗成地用变量名全部被大写代表常量. AGE_OF_OLDBOY = 56 基础运算符补充 1.算术运算 加减乘除+ - ...

  4. C++ Primer 笔记——标准库类型string

    1.如果使用等号初始化一个变量,实际上执行的是拷贝初始化,编译器吧等号右侧的初始值拷贝到新创建的对象中去:如果不使用等号则执行的是直接初始化. std::string str = "Test ...

  5. js call() 笔记

    var ctrl = function() {}; ctrl.view = function() { return { show: function() { console.log("vie ...

  6. 20165323 结对编程之四则运算week2-整体总结

    一.需求 实现一个命令行程序,要求: 1.自动生成小学四则运算题目(加.减.乘.除) 2.支持整数 3.支持多运算符(比如生成包含100个运算符的题目) 4.支持真分数 5.能判断错误,在输入错误结果 ...

  7. C++ 定位new运算符

    这里说的定位new运算符,是一种相对于普通的new运算符,可以指定内存地址的运算符,程序直接使用我们提供的地址,不管它是否已经被使用,而且可以看到新值直接覆盖在旧值上面. 定位new运算符直接使用传递 ...

  8. es6 新增数据类型Symbol

    es6在string number boolean null undefined object之外又新增了一种Symbol类型. Symbol意思是符号,有一个特性—每次创建一个Symbol值都是不一 ...

  9. 【转】通过 INotifyPropertyChanged 实现观察者模式

    通过 INotifyPropertyChanged 实现观察者模式 原博客地址 http://frankdzu.blog.sohu.com/117654536.html 普通观察者模式存在的问题 我们 ...

  10. Python_时间复杂度概念

    时间频度:一个算法中的语句执行次数称为语句频度或时间频度,记为T(n)(T代表次数,n代表问题规模) 时间复杂度:呈现时间频度的变化规律,记为T(n)=O(f(n)) 指数时间:一个问题求解所需的执行 ...