最长回文子串:Manacher算法
2016-07-15 11:07
197 查看
详解见:
http://blog.csdn.net/xingyeyongheng/article/details/9310555
解析:
首先预处理字符串,在字符串首尾和每两个字符之间插入特殊符号(例如’#’)使字符串变成奇数长度,为了进一步减少编码复杂度,还可以再字符串开始再加入另一个特殊字符,这样就不用特殊处理越界问题了。
然后利用计算字符串的P[i]数组来记录以字符S[i]为中心的最长回文子串向左/右扩张的长度即回文半径。
eg:
计算半径数组:
最后遍历一次半径数组,值最大的就是最长回文子串。
练习:
http://acm.hdu.edu.cn/showproblem.php?pid=3068
分析&题解:
直接用Manacher算法求最长回文子串,不知为何之前自己敲的一直TLE,感觉差不多,后来找了个AC代码,以后直接套模板吧 (= =)
AC 代码:
http://blog.csdn.net/xingyeyongheng/article/details/9310555
解析:
首先预处理字符串,在字符串首尾和每两个字符之间插入特殊符号(例如’#’)使字符串变成奇数长度,为了进一步减少编码复杂度,还可以再字符串开始再加入另一个特殊字符,这样就不用特殊处理越界问题了。
然后利用计算字符串的P[i]数组来记录以字符S[i]为中心的最长回文子串向左/右扩张的长度即回文半径。
eg:
S: # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 # P: 1 2 1 2 5 2 1 4 1 2 1 6 1 2 1 2 1 (p.s. 可以看出,P[i]-1正好是原字符串中以S[i]为中心形成回文串的总长度)
计算半径数组:
void manacher()//p[]为半径数组,str[]为处理过后字符串 { int id, mx, i; id = mx = 0; for (i=1; i<=l; ++i) { if (mx > i) p[i] = min(p[2*id-i], mx-i+1); else p[i] = 1; while (str[i+p[i]]==str[i-p[i]]) ++p[i]; if (p[i]+i-1>mx) { id = i; mx = i + p[i] - 1; } } }
最后遍历一次半径数组,值最大的就是最长回文子串。
练习:
http://acm.hdu.edu.cn/showproblem.php?pid=3068
分析&题解:
直接用Manacher算法求最长回文子串,不知为何之前自己敲的一直TLE,感觉差不多,后来找了个AC代码,以后直接套模板吧 (= =)
AC 代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int nn = 220050; char str[nn], str0[nn]; int len, p[nn]; void manacher() { int id, mx, i; id = mx = 0; for (i=1; i<=len; ++i) { if (mx > i) p[i] = min(p[2*id-i], mx-i+1); else p[i] = 1; while (str[i+p[i]]==str[i-p[i]]) ++p[i]; if (p[i]+i-1>mx) { id = i; mx = i + p[i] - 1; } } } int main(){ while (scanf("%s", str0) != EOF) { len = strlen(str0); str[0] = '$'; str[1] = '#'; for (int i=0; i<len; ++i) { str[2*i+2] = str0[i]; str[2*i+3] = '#';//预处理数组 } len = 2*len+1; str[len+1] = '\0'; manacher(); int ans = 0; for (int i=1; i<len; ++i) if (ans < p[i]-1) ans = p[i]-1; printf("%d\n", ans ); } return 0; }
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACMer博客瀑布流分析
- ACM程序设计大赛题目分类
- 2015年acm国内排名
- 计算字符串最后一个单词长度
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- HDOJ 1002 A + B Problem II (Big Numbers Addition)
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1002