首页 > 代码库 > Manacher算法--O(n)内求回文子串
Manacher算法--O(n)内求回文子串
昨天做了leetcode里的 Longest Palindromic Substring ,一开始用动态规划O(N^2),不管怎么改都超时了。。。于是在大神的帮助下,找到了传说中的Manacher算法,居然能在O(n)内求出来,瞬间给跪了。
本屌认为,这个算法主要是充分的利用了以前的匹配的结果,来起到了降低时间复杂度的作用,这点跟KMP算是有点类似。在预处理时有个小技巧就是将第0,1为设为"$#",后面每隔一位加一个“#”,这样既能够防止数组越界问题又能够,避免奇数和偶数的讨论。如 aaaa 就变成 $#a#a#a#a#
这是核心部分代码:
void Manacher(int n) { int mx=0; int id; p[0]=0; for(int i=1;i<n;i++) { p[i]=1; if(mx>i) { p[i]=min(p[2*id-i],mx-i); } while(str[i-p[i]]==str[i+p[i]]) p[i]++; if(i+p[i]>mx) { id=i; mx=i+p[i]; } } }
P[i]记录的是以字符str[i]为中心的最长回文串的半径。且这里有一个很好的性质,P[i]-1就是该回文子串在原串中的长度(包括‘#’)
举个例子:
原串: w aa bwsw f d
新串: # w# a # a # b# w # s # w # f # d #
辅助数组P: 1 2 1 2 3 2 1 2 1 2 1 4 1 2 1 2 1 2 1
接下来就是关键部分了,如何运用前面的结果
if(mx>i) { p[i]=min(p[2*id-i],mx-i); }
接下来就借用下大神的图了
有两种情况
下附上某大牛的地址:http://blog.csdn.net/ggggiqnypgjg/article/details/6645824
这个是题目链接:https://oj.leetcode.com/problems/longest-palindromic-substring/
Longest Palindromic Substring
Total Accepted: 11893 Total Submissions: 58709My SubmissionsGiven 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.