Manacher算法图解
生活随笔
收集整理的這篇文章主要介紹了
Manacher算法图解
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
看了好久的Manacher算法,覺(jué)得還是要自己畫(huà)一遍,自己把代碼寫(xiě)一遍才能理解
下面分享一下,如果有錯(cuò),希望指正
簡(jiǎn)陋版本的,但是他基本只是做到了求取最長(zhǎng)回文字符串,嚴(yán)格來(lái)說(shuō)它并不是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-馬拉車算法 時(shí)間復(fù)雜度O(n)
互聯(lián)網(wǎng)偵察微信公眾號(hào)講解,雖然文章很長(zhǎng),但是他講解的十分清楚
這篇博文簡(jiǎn)單的介紹了思路
下面是核心代碼,我們先看圖
//Manacher算法計(jì)算過(guò)程 int MANACHER(char *st, int len) {int mx = 0, ans = 0, po = 0;//mx即為當(dāng)前計(jì)算回文串最右邊字符的最大值for (int i = 1; i <= len; i++){if (mx > i)Len[i] = min(mx - i, Len[2 * po - i]);//在Len[j]和mx-i中取個(gè)小elseLen[i] = 1;//如果i>=mx,要從頭開(kāi)始匹配while (st[i - Len[i]] == st[i + Len[i]])Len[i]++;if (Len[i] + i > mx)//若新計(jì)算的回文串右端點(diǎn)位置大于mx,要更新po和mx的值{mx = Len[i] + i;po = i;}ans = max(ans, Len[i]);}return ans - 1;//返回Len[i]中的最大值-1即為原串的最長(zhǎng)回文子串額長(zhǎng)度 }首先對(duì)字符串進(jìn)行預(yù)處理,處理原因是防止偶數(shù)問(wèn)題(可看前面的博文)
處理后的結(jié)果進(jìn)行Manacher算法。
第一個(gè)@是0,其余默認(rèn)從1開(kāi)始計(jì)數(shù)
首先看3 的左右都是#號(hào)所以1+1 = 2;
到了1,它可以數(shù)到6,碰到了@就不相等了,而他的回文字符串長(zhǎng)度也是6
等到了1右邊的#號(hào),我們就可以根據(jù)對(duì)稱特點(diǎn),求出他和1左邊的#號(hào)是同一個(gè)值(前提是這個(gè)沒(méi)有超過(guò)有邊界,黃色橫線所示)
到這里基本就結(jié)束了
這里給出完整代碼,可以自己跑一編,看看效果
#define maxn 1000010 #include <cstdio> #include <iostream> #include <algorithm>using namespace std;char str[maxn] = {"3212343219"};//原字符串 char tmp[maxn << 1];//轉(zhuǎn)換后的字符串 int Len[maxn << 1];//轉(zhuǎn)換原始串 int INIT(char *st) {int i, len = strlen(st);tmp[0] = '@';//字符串開(kāi)頭增加一個(gè)特殊字符,防止越界for (i = 1; i <= 2 * len; i += 2){tmp[i] = '#';tmp[i + 1] = st[i / 2];}tmp[2 * len + 1] = '#';tmp[2 * len + 2] = '$';//字符串結(jié)尾加一個(gè)字符,防止越界tmp[2 * len + 3] = 0;return 2 * len + 1;//返回轉(zhuǎn)換字符串的長(zhǎng)度 } //Manacher算法計(jì)算過(guò)程 int MANACHER(char *st, int len) {int mx = 0, ans = 0, po = 0;//mx即為當(dāng)前計(jì)算回文串最右邊字符的最大值for (int i = 1; i <= len; i++){if (mx > i)Len[i] = min(mx - i, Len[2 * po - i]);//在Len[j]和mx-i中取個(gè)小elseLen[i] = 1;//如果i>=mx,要從頭開(kāi)始匹配while (st[i - Len[i]] == st[i + Len[i]])Len[i]++;if (Len[i] + i > mx)//若新計(jì)算的回文串右端點(diǎn)位置大于mx,要更新po和mx的值{mx = Len[i] + i;po = i;}ans = max(ans, Len[i]);}return ans - 1;//返回Len[i]中的最大值-1即為原串的最長(zhǎng)回文子串額長(zhǎng)度 }int main() {int len = INIT(str);MANACHER(tmp, len); }總結(jié)
以上是生活随笔為你收集整理的Manacher算法图解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 输卵管结扎了能做试管婴儿吗
- 下一篇: ySQL挑战搭建一个简易的成绩管理系统的