Longest Palindromic Substring
2016-02-16 16:32
197 查看
Given a string S,
find the longest palindromic substring in S.
You may assume that the maximum length of S is
1000, and there exists one unique longest palindromic substring.
Manacher算法计算最长回文串
1. 字符串预处理
由于回文字符串存在奇偶两种情况
aba abba
将两者情况统一处理将方便算法的执行,所以算法第一步便是将字符串统一,
2*length+1 可以将字符串统一变为奇数长度,字符串经过变化得到如下新的字符串。
2.用数组p来记录以各个字符为中心的回文串半径
Str:$ # a # b # a # &
P :1 1 2 1 4 1 2 1 1
P的计算方法
以每个字符为中心,不断向外扩展,比较左右字符而得,但这种做法过于耗时。在Manacher算法中以非常精妙的方法进行了改进。对于p[i](以str[i]为中心的回文串半径)计算方式如下,首先大括号的范围表示以currentCenter为中心的回文串范围,j是i相对于currentCenter的索引,boundary为界限索引。
j=currentCenter-(i-currentCenter)=2*currentCenter-i;
2.1p[i]初始值计算分为两种情况:
(1)p[j]回文串依旧在p[currentCenter]范围内,则p[i]=p[j];
(2)p[j]回文串不在p[currentCenter]范围内,则p[i]=boundary-i;
2.2p[i]后续值扩展:
任意一个p[i]在初始值的基础上都可以继续递增,只要左右相等即可
3.最长回文串计算
只要通过遍历一遍p数组便可以得到最长回文串
代码如下:
find the longest palindromic substring in S.
You may assume that the maximum length of S is
1000, and there exists one unique longest palindromic substring.
Manacher算法计算最长回文串
1. 字符串预处理
由于回文字符串存在奇偶两种情况
aba abba
将两者情况统一处理将方便算法的执行,所以算法第一步便是将字符串统一,
2*length+1 可以将字符串统一变为奇数长度,字符串经过变化得到如下新的字符串。
2.用数组p来记录以各个字符为中心的回文串半径
Str:$ # a # b # a # &
P :1 1 2 1 4 1 2 1 1
P的计算方法
以每个字符为中心,不断向外扩展,比较左右字符而得,但这种做法过于耗时。在Manacher算法中以非常精妙的方法进行了改进。对于p[i](以str[i]为中心的回文串半径)计算方式如下,首先大括号的范围表示以currentCenter为中心的回文串范围,j是i相对于currentCenter的索引,boundary为界限索引。
j=currentCenter-(i-currentCenter)=2*currentCenter-i;
2.1p[i]初始值计算分为两种情况:
(1)p[j]回文串依旧在p[currentCenter]范围内,则p[i]=p[j];
(2)p[j]回文串不在p[currentCenter]范围内,则p[i]=boundary-i;
2.2p[i]后续值扩展:
任意一个p[i]在初始值的基础上都可以继续递增,只要左右相等即可
3.最长回文串计算
只要通过遍历一遍p数组便可以得到最长回文串
代码如下:
class Solution { public: string longestPalindrome(string s) { vector<char> str; init(s,str); vector<int> p; pCalculate(p,str); int beginIndex=0,endIndex=0, maxLength = 0; for (int i=1;i<p.size();++i) { if (p[i]>maxLength) { maxLength = p[i]; if (maxLength>=2) { beginIndex = (i-p[i]+2)/2-1; endIndex = (i+p[i]-2)/2-1; } } } return s.substr(beginIndex,endIndex-beginIndex+1); } void init(string s, vector<char>& str) { str.push_back('$'); str.push_back('#'); for (int i=0;i<s.size();++i) { str.push_back(s.at(i)); str.push_back('#'); } str.push_back('&'); } void pCalculate(vector<int>& p,vector<char>& str) { int boundary = 0; int currentCenter = 0; p.push_back(1); for (int i=1;i<str.size()-1;++i) { if (boundary>i) { p.push_back(min(p[currentCenter*2-i],boundary-i)); } else { p.push_back(1); } while (str[i-p[i]]==str[i+p[i]]) { p[i]++; } if (p[i]+i>boundary) { boundary = p[i]+i; currentCenter = i; } } } };
相关文章推荐
- DefaultHttpClient使用
- CPU微程序控制器
- 使用AJAX完成用户名是否存在异步校验(基于SSH框架)
- 一个优化极点的ViewHolder
- ava中的匿名内部类总结
- Git本地仓库 (git基本概念)
- iOS深入学习(Block全面分析)
- document.execCommand()说明
- 搭建maven多模块工程
- unity扩展MonoBehaviour
- TAB 切换 防刷新
- 一个优化极点的ViewHolder
- 【Redis学习笔记(七)】 Redis中的事务
- MongoDB count()的正确用法
- SSL协议握手过程
- tcp 4种定时器
- 手游与App测试如何快速转型? —— 过来人科普手游与App测试四大区别
- soureTree使用
- hdu 5626 数学题
- Activity启动模式