欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

Manacher算法图解

发布时间:2023/11/30 50 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Manacher算法图解 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

看了好久的Manacher算法,觉得还是要自己画一遍,自己把代码写一遍才能理解

下面分享一下,如果有错,希望指正

简陋版本的,但是他基本只是做到了求取最长回文字符串,严格来说它并不是Manacher’s Algorithm-马拉车算法

#include<stdio.h> 、char qdu[100050]; int manachar() {int i;int res = 0;for (i = 1; qdu[i]; i++){int l = i;int r = i;while (qdu[i] == qdu[r + 1])r++;i = r;while (qdu[l - 1] == qdu[r + 1]) {r++;l--;}if (res < r - l + 1)res = r - l + 1;}return res; } int main() {int loop;qdu[0] = '$';gets(qdu + 1);printf("%d\n", manachar());return 0; }

Manacher’s Algorithm-马拉车算法 时间复杂度O(n)

互联网侦察微信公众号讲解,虽然文章很长,但是他讲解的十分清楚

这篇博文简单的介绍了思路

下面是核心代码,我们先看图

//Manacher算法计算过程 int MANACHER(char *st, int len) {int mx = 0, ans = 0, po = 0;//mx即为当前计算回文串最右边字符的最大值for (int i = 1; i <= len; i++){if (mx > i)Len[i] = min(mx - i, Len[2 * po - i]);//在Len[j]和mx-i中取个小elseLen[i] = 1;//如果i>=mx,要从头开始匹配while (st[i - Len[i]] == st[i + Len[i]])Len[i]++;if (Len[i] + i > mx)//若新计算的回文串右端点位置大于mx,要更新po和mx的值{mx = Len[i] + i;po = i;}ans = max(ans, Len[i]);}return ans - 1;//返回Len[i]中的最大值-1即为原串的最长回文子串额长度 }

首先对字符串进行预处理,处理原因是防止偶数问题(可看前面的博文)
处理后的结果进行Manacher算法。
第一个@是0,其余默认从1开始计数
首先看3 的左右都是#号所以1+1 = 2;
到了1,它可以数到6,碰到了@就不相等了,而他的回文字符串长度也是6
等到了1右边的#号,我们就可以根据对称特点,求出他和1左边的#号是同一个值(前提是这个没有超过有边界,黄色横线所示)
到这里基本就结束了

这里给出完整代码,可以自己跑一编,看看效果

#define maxn 1000010 #include <cstdio> #include <iostream> #include <algorithm>using namespace std;char str[maxn] = {"3212343219"};//原字符串 char tmp[maxn << 1];//转换后的字符串 int Len[maxn << 1];//转换原始串 int INIT(char *st) {int i, len = strlen(st);tmp[0] = '@';//字符串开头增加一个特殊字符,防止越界for (i = 1; i <= 2 * len; i += 2){tmp[i] = '#';tmp[i + 1] = st[i / 2];}tmp[2 * len + 1] = '#';tmp[2 * len + 2] = '$';//字符串结尾加一个字符,防止越界tmp[2 * len + 3] = 0;return 2 * len + 1;//返回转换字符串的长度 } //Manacher算法计算过程 int MANACHER(char *st, int len) {int mx = 0, ans = 0, po = 0;//mx即为当前计算回文串最右边字符的最大值for (int i = 1; i <= len; i++){if (mx > i)Len[i] = min(mx - i, Len[2 * po - i]);//在Len[j]和mx-i中取个小elseLen[i] = 1;//如果i>=mx,要从头开始匹配while (st[i - Len[i]] == st[i + Len[i]])Len[i]++;if (Len[i] + i > mx)//若新计算的回文串右端点位置大于mx,要更新po和mx的值{mx = Len[i] + i;po = i;}ans = max(ans, Len[i]);}return ans - 1;//返回Len[i]中的最大值-1即为原串的最长回文子串额长度 }int main() {int len = INIT(str);MANACHER(tmp, len); }

总结

以上是生活随笔为你收集整理的Manacher算法图解的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。