manacher算法详解
来源:互联网 发布:利雅得机场数据 编辑:程序博客网 时间:2024/06/01 07:39
今天同学问我求字符串中最大回文串的问题,最先想到的就是暴力了,时间复杂度为O(n*n),而且还要考虑回文串长
度为奇偶两种情况。后来同学说网上有O(n)的解法,就搜了下,果然manacher是在O(n)的时间复杂度里解决的。但是
里面那个求数组p的过程还是不怎么理解,特在此发表希望得到论坛朋友们的指教。下面是实现代码:
#include<iostream>#include<cstring>using namespace std;int manacher (char* s, int len){int nlen = 2 * len + 3;char* str = new char[nlen];int i = 0;int max = 0;str[0] = '$';str[1] = '#';for (; i < len; i++){str[i * 2 + 2] = s[i];str[i * 2 + 3] = '#';}str[nlen - 1] = 0;int* p = new int[nlen];for (int i = 1; i < nlen; i++){p[i] = 0;}int id = 0;for (i = 1; i < nlen; i++){if (max > i)p[i] = min(p[2*id-i], p[id]+id-i);elsep[i] = 1;while (str[i+p[i]] == str[i-p[i]])p[i]++;if (p[i]+i > max){max = p[i] + i;id = i;}}int mx = 0;for (i = 1; i < nlen; i++){if (mx < p[i] - 1)mx = p[i] - 1;}return mx;}int main(){char ch[100];while (cin >> ch){cout << manacher(ch, strlen(ch)) << endl;}return 0;}
补:后来又网上找了好久,终于找到一个写的比较符合我的习惯的了。看完终于理解了这个算法。这个算法的核心就
是P的求解了,也就是
if (max > i) p[i] = min(p[2*id-i], p[id]+id-i);else p[i] = 1;这里max表示的是扫面str[i]后,匹配到的最远的位置。而id则记录取这个max的i值。
if (max > i) p[i] = min(p[2*id-i], p[id]+id-i);这个代码就是为了避免很多没必要的重复匹配。这个就利用了回文串的对称性。
i点关于id点的对称点j = 2*id - i。根据对称性,p[j]的回文串也是可以对称到i这边的,但是如果p[j]的回文串对称过来以
后超过max的话,超出部分就不能对称过来,因为超出的部分是我们还没有匹配的。所以我们这里p[i]的值应该取两者
中的较小者:p[i] = min(p[2*id-i], max-i)。然后通过while (str[i+p[i]] == str[i-p[i]]) p[i]++;继续匹配后面的。
- manacher算法详解
- manacher算法详解
- manacher算法详解
- Manacher算法详解
- Manacher算法详解
- Manacher算法详解
- hdu3068之manacher算法+详解
- hdu3068之manacher算法+详解
- hdu3068之manacher算法+详解
- manacher 算法详解 pku 3974
- 详解manacher算法,及其扩展
- 马拉车算法(Manacher)详解
- Manacher(马拉车)算法详解
- Manacher算法
- Manacher算法
- Manacher算法
- Manacher算法
- Manacher 算法
- 求一个数的平方根(C语言实现)
- 今天你代言了吗?WPS版“陈欧体”引热议
- 查看SQL数据库里每个表的记录数据
- java环境变量最佳配置
- android 2.3 ethernet
- manacher算法详解
- Swinghacks——获取系统图标
- ACM小问题总结
- C/C++中结构体变量字节对齐讨论
- POJ 3620 Avoid The Lakes【DFS水题练格式Avoid The Lakes Time Limit: 1000MSMemory Limit: 65536K Total Sub】
- android 电源管理
- p4jorm 1.0.3版本
- 十进制转十六进制
- XP装Redhat双系统过程