对于字符串S, 要找到它最长的回文子串,能想到的最暴力方法,应该是对于每个元素i-th都向左向右对称搜索,最后用一个数组span 记录下相对应元素i-th为中心的回文子串长度。

那么问题来了:

  1. 这样的方法,对于奇回文子串和偶回文子串的处理不一样,比如所“acbca” 和“acbbca”

  2. 计算冗余,e.g. ”sscssabcccchccccba“中, 自左向右遍历计算的话,会发现, ”abcccchccccba“是对称的,而这个回文字符串里又左右对称分别包含了两个回文子字符”cccc“和”cccc“, 在对第二个”cccc“字符串遍历的时候,其实可以利用到”abcccchccccba“的对称性来直接赋值,而不用再次计算

于是,引出了Manacher's 算法:

  1. 为了可以对奇偶回文字符串不加区分地处理,对输入字符串增加边界元素(输入字符串S长度为N -> S2长度为2*N+1):e.g. ”aabbbcc“ -> "#a#a#b#b#b#c#c#" , ”aabbcc“ -> "#a#a#b#b#c#c#"

  2. 对于S2字符串,自左向右,每个字符逐个计算和处理

    1)用span[maxInputStringLength*2+1]数组来记录每个元素i-th为中心的回文字符串长度 : 初始化 span[0] = 0

    2)用center 和 rightBoundary 来记录上一个已知的回文字符串中心index和最右边界index :初始化 center = 0, rightBoundary = 0

    3)用 i 表示当前处理的元素, i2 表示 以 center 为中心的 center左侧 i 对称 元素下标 : i2 = center - (i - center)= center * 2 - i

    4)加上已知的回文子串信息之后,假设已经处理了S2[0, i-1]范围的元素,那么已知的回文子串中心center 必然属于[0, i-1]区间, 但是对于rightBoundary和i的关系可以有三种情况:

      a)当前处理的元素(index = i)以 center为中心,对称的元素(index = i2)上有,span[i2] < rightBoundary - i - 1, 表示i2点的回文字符串最左端不会超过leftBoundary的长度,利用了已知的回文字符串信息辅助说明,当前以i为中心的回文字符串将和i2完全对称,span[i] = span[i2]

      

      b)当前处理的元素(index = i)以 center为中心,对称的元素(index = i2)上有,span[i2] >= rightBoundary - i - 1, 表示 i2 点的回文字符串最左端已经超过了leftBoundary的范围,不能利用已知回文字符串直接赋值,但还是可以利用对称性,使得对称搜索从rightBoundary处开始,这样可以减少计算

      

      c)当前处理的元素(index = i)并不在已知回文串的记录范文内,那么久没有辅助信息,需要从i元素的左右对称搜索,得到span[i]的值

      

    5)最后要更新center和rightBoundary的值,使得已知回文字符串的覆盖范围右移,这样可以持续辅助搜索

  

 const int maxStringLength = ;

 string longestPalindrome(string s) {

     if (s.empty()) return "";

     ///add boundary
string s2;
for (int i = ; i < s.size(); i++) {
s2.push_back('#');
s2.push_back(s[i]);
}
s2.push_back('#'); /// setting
int span[maxStringLength] = {};
span[] = ; // init the first element's length of palindrome
int center = , rightBoundary = ;
int left = , right = ; ///traverse
for (int i = ; i < s2.size(); i++) {
if (i <= rightBoundary) {
int i2 = center * - i;// center - (i - center)
if (span[i2] < (rightBoundary - i - )) {
span[i] = span[i2];
left = -;
}
else {
span[i] = rightBoundary - i;
right = rightBoundary + ;
left = i * - right; //i - (right - i)
}
}
else {
span[i] = ;
left = i - ;
right = i + ;
} while (left >= && right < s2.size() && s2[left] == s2[right]) {
span[i] ++;
left--;
right++;
} if ((i + span[i]) > rightBoundary) {
center = i;
rightBoundary = i + span[i];
}
} /// find the max span length
int maxSubstringCenter = , maxSubstringLen = ;
for (int i = ; i < s2.size(); i++) {
if (span[i] > maxSubstringLen) {
maxSubstringLen = span[i];
maxSubstringCenter = i;
}
} /// remove boundary '#' from substring
string result;
for (int i = maxSubstringCenter - maxSubstringLen; i <= maxSubstringCenter + maxSubstringLen; i++) {
if (s2[i] != '#')
result.push_back(s2[i]);
} return result;
}

【算法】最长回文子串 longest palindrome substring的更多相关文章

  1. [译]最长回文子串(Longest Palindromic Substring) Part I

    [译]最长回文子串(Longest Palindromic Substring) Part I 英文原文链接在(http://leetcode.com/2011/11/longest-palindro ...

  2. 领扣-5 最长回文子串 Longest Palindromic Substring MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. [译+改]最长回文子串(Longest Palindromic Substring) Part II

    [译+改]最长回文子串(Longest Palindromic Substring) Part II 原文链接在http://leetcode.com/2011/11/longest-palindro ...

  4. 最长回文子串(Longest Palindromic Substring)-DP问题

    问题描述: 给定一个字符串S,找出它的最大的回文子串,你可以假设字符串的最大长度是1000,而且存在唯一的最长回文子串 . 思路分析: 动态规划的思路:dp[i][j] 表示的是 从i 到 j 的字串 ...

  5. [Swift]LeetCode5. 最长回文子串 | Longest Palindromic Substring

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  6. LeetCode.5-最长回文子串(Longest Palindromic Substring)

    这是悦乐书的第342次更新,第366篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Medium级别的第3题(顺位题号是5).给定一个字符串s,找到s中最长的回文子字符串. 您可以假设s ...

  7. Manacher算法----最长回文子串

    题目描述 给定一个字符串,求它的最长回文子串的长度. 分析与解法 最容易想到的办法是枚举所有的子串,分别判断其是否为回文.这个思路初看起来是正确的,但却做了很多无用功,如果一个长的子串包含另一个短一些 ...

  8. Manacher算法——最长回文子串

    一.相关介绍 最长回文子串 s="abcd", 最长回文长度为 1,即a或b或c或d s="ababa", 最长回文长度为 5,即ababa s="a ...

  9. [Swift]LeetCode409. 最长回文串 | Longest Palindrome

    Given a string which consists of lowercase or uppercase letters, find the length of the longest pali ...

随机推荐

  1. 西交校赛 I. GZP and CS(数位dp)

    I. GZP and CS GZP love to play Counter-Strike(CS). One day GZP was playing a mod of CS. The counter- ...

  2. [Selenium] Actions.doubleClick

    WebElement el = page.getTable_AssetMixesName().get(index); Actions action = new Actions(driver); act ...

  3. 洛谷P1466集合——背包

    题目:https://www.luogu.org/problemnew/show/P1466 水题,注意开long long; 代码如下: #include<iostream> #incl ...

  4. Spring注解的(List&Map)特殊注入功能

    一.先看一个示例演示:spring注解的一个特殊的注入功能. 首先,是定义一个接口,3个实现类. public interface GreetService { public String sayHe ...

  5. UI控件初始化问题:initWithFrame和initWithCoder、aweakFromNib的执行

    在iOS学习和程序开发过程中,我们经常会遇到一些自定义UI控件或控制器在初始化时出现问题,尤其在大家刚开始接触时,几种初始化方法的作用以及调用的时机往往容易混淆,这也跟我们对iOS程序设计中,类的创建 ...

  6. View Programming Guide for iOS ---- iOS 视图编程指南(一)

    Next About Windows and Views 关于窗口和视图 In iOS, you use windows and views to present your application’s ...

  7. 连接mysql报错-Can't connect to MySQL server on

    1.问题: 在Windows 上远程连接数据库报错-Can't connect to MySQL server on... 但是重启系统后就可以连接: 2.这种原因大致是因为系统缓冲区空间不足或列队已 ...

  8. hdoj1272【并查集】

    因为是第二遍,所以题目也没怎么看,然后一开始的思路就是如果每次输入两个点的时候判断是不是同一个集合,如果同一个就是No,然后就wa了,想想也是,然后瞄了一下题解,还要判连通-真是蠢死了-多个集合都想不 ...

  9. bzoj 4199: [Noi2015]品酒大会【后缀数组+单调栈+并查集】

    用SA求出height数组,然后发现每个height值都有一个贡献区间(因为点对之间要依次取min) 用单调栈处理出区间,第一问就做完了 然后用并查集维护每个点的贡献(?),从大到小枚举height, ...

  10. LeetCode.896-单调数组(Monotonic Array)

    这是悦乐书的第345次更新,第369篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第210题(顺位题号是896).如果数组单调递增或单调递减,则数组是单调的.如果对于所有 ...