【算法】最长回文子串 longest palindrome substring
对于字符串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的更多相关文章
- [译]最长回文子串(Longest Palindromic Substring) Part I
[译]最长回文子串(Longest Palindromic Substring) Part I 英文原文链接在(http://leetcode.com/2011/11/longest-palindro ...
- 领扣-5 最长回文子串 Longest Palindromic Substring MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- [译+改]最长回文子串(Longest Palindromic Substring) Part II
[译+改]最长回文子串(Longest Palindromic Substring) Part II 原文链接在http://leetcode.com/2011/11/longest-palindro ...
- 最长回文子串(Longest Palindromic Substring)-DP问题
问题描述: 给定一个字符串S,找出它的最大的回文子串,你可以假设字符串的最大长度是1000,而且存在唯一的最长回文子串 . 思路分析: 动态规划的思路:dp[i][j] 表示的是 从i 到 j 的字串 ...
- [Swift]LeetCode5. 最长回文子串 | Longest Palindromic Substring
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- LeetCode.5-最长回文子串(Longest Palindromic Substring)
这是悦乐书的第342次更新,第366篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Medium级别的第3题(顺位题号是5).给定一个字符串s,找到s中最长的回文子字符串. 您可以假设s ...
- Manacher算法----最长回文子串
题目描述 给定一个字符串,求它的最长回文子串的长度. 分析与解法 最容易想到的办法是枚举所有的子串,分别判断其是否为回文.这个思路初看起来是正确的,但却做了很多无用功,如果一个长的子串包含另一个短一些 ...
- Manacher算法——最长回文子串
一.相关介绍 最长回文子串 s="abcd", 最长回文长度为 1,即a或b或c或d s="ababa", 最长回文长度为 5,即ababa s="a ...
- [Swift]LeetCode409. 最长回文串 | Longest Palindrome
Given a string which consists of lowercase or uppercase letters, find the length of the longest pali ...
随机推荐
- HNOI2008 越狱 (组合数学)
传送门 应该是HNOI2008年最简单的一道题了吧……简单的组合数题,不过要换个思路. 我们直接考虑发生越狱的情况似乎有点复杂,那我们换个思路,考虑不发生越狱的情况,也就是两个有相同宗教的人不会坐在一 ...
- angularJS ng-if的用法
ng-if主要是用来判断是否显示,也可以做为而者选择其中一个的方法,满足判断条件ng-if="变量名" 显示,否者不显示,也可以用ng-if="!变量名"取反, ...
- ASP.NET Core:Pages
ylbtech-ASP.NET Core:Pages 1.返回顶部 1._Layout.cshtm <!DOCTYPE html> <html> <head> &l ...
- iOS 中的 Block
参考:链接 (1)block作为本地变量(local variable) returnType (^blockName)(parameterTypes) = ^returnType(parameter ...
- Spring AOP schema找不到报错 原
转自:https://my.oschina.net/zetaplusae/blog/144821 使用jersey+spring构建RESTful服务,并将应用部署在不能连接外网的服务器上.部署时,报 ...
- 交通规划_dijkstra
问题描述 G国国王来中国参观后,被中国的高速铁路深深的震撼,决定为自己的国家也建设一个高速铁路系统. 建设高速铁路投入非常大,为了节约建设成本,G国国王决定不新建铁路,而是将已有的铁路改造成高速铁路. ...
- (水题)Codeforces - 630H - Benches
https://codeforces.com/problemset/problem/630/H 又一个组合数学的问题,我们先考虑在 $n$ 列中选出 $5$ 列来放椅子,然后对第一列有 $n$ 种放法 ...
- Luogu P4139 上帝与集合的正确用法【扩展欧拉定理】By cellur925
题目传送门 题目中的式子很符合扩展欧拉定理的样子.(如果你还不知扩展欧拉定理,戳).对于那一堆糟心的2,我们只需要递归即可,递归边界是模数为1. 另外,本题中好像必须要用快速乘的样子...否则无法通过 ...
- Mantis优化改造(技术篇)
为什么要写这篇? 既然都过去这么久了,都回忆不起来了,为什么还要整理出来这篇文章呢? 这还要追溯到2018年3月份. 当时换工作,面试了国内某知名电视厂商. 简历上面写了我优化改造了bug管理系统ma ...
- Jquery | 基础 | 慕课网 | 层级选择器
选择器中的层级选择器处理关系类型: 子元素 后代元素 兄弟元素 相邻元素 <!DOCTYPE html> <html> <head> <meta http-e ...