1. 程式人生 > >並不對勁的manacher算法

並不對勁的manacher算法

algo nds 分享圖片 ans 奇怪 hid pen 還要 manacher

有些時候,後綴自動機並不能解決某些問題,或者解決很麻煩。這時就有各種神奇的字符串算法了。

manacher算法用來O(|S|)地求出字符串S的最長的回文串的長度。這是怎麽做到的呢?

並不對勁的暴力選手在剛見到求字符串S的最長的回文串的長度這個問題時,第一反應就是枚舉每一個位置為回文串的對稱軸,再暴力地判斷。由於回文串的對稱軸可能在縫隙處,對於奇偶還要特判。這時最好每隔一個字符插入一個奇怪的字符。對暴力做一些優化,就是用二分+哈希來判斷。不過這也只能o(|S| log2|S|)地做出來。能不能利用回文串的某些性質呢?

設r[i]表示以i為對稱軸,是S[i+1]與S[i-1],S[i+2]與S[i-2],…,S[i+x]與S[i-x],相等的最大的x。定義s(i,r[i])表示以i為對稱軸的且右端點為i+r[i]的回文串。

那麽i-r[i]到i+r[i]這一段就是對稱的。

記已算出的最大的i+r[i]為maxr (也就是已算出的回文串的右端點中最靠右的),maxr的i為maxi。

若要算出r[a],則:

若a>=maxr,直接按定義暴力地求出r[a]。

若a<maxr,則先找出a關於maxi的對稱點b。則r[a]>=min(r[b],maxr-a)。

技術分享圖片

當r[b]<maxr-a時,a+r[b]<maxr,所以s(b,r[b])肯定被s(maxi,maxr)包含。由於a與b關於maxi對稱,所以以a為對稱軸的回文串中,肯定有一個等於ls(b,r[b])。又因為r[b]是b的最長回文子串的右端點,所以S[b-r[b]-1]!=S[b+r[b]+1],根據對稱性又能推出S[a-r[b]-1]!=S[a+r[b]+1]。所以此時r[a]=r[b]。

當r[b]>=maxr-a時,b-r[b]<maxi-r[maxi],也就是說,s(b,r[b])中有一部分在s(maxi,maxr)外,不符合對稱性。這一部分是不能算的。所以此時r[a]>=min(r[b],maxr-a)

這樣先令r[a]=min(r[b],maxr-i),剩下的按定義暴力求就行了。

字符串S的最長的回文串的長度就是最大的r[i]了。這是因為如果算上奇怪的字符,那麽r[i]對應的回文串長度是r[i]*2+1。修改後的字符串每隔一個字符就有一個奇怪的字符。這些奇怪的字符都相同,所以r[i]對應回文串的第一個字符和最後一個字符都是奇怪的字符(形如#a#b#a#或#a#a#)。那麽不是奇怪的字符一共有(r[i]*2+1-1)/2=r[i]個。

至於時間復雜度,並不對勁的人並不想不證明。因為每次有意義的比較都是maxr之後的部分,比較過的部分又會更新maxr。總的來看就是maxr將整個字符串掃了一遍,時間復雜度是O(|S|),而且很好寫。

不太清楚它能出成什麽題?

技術分享圖片
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn 11000010
using namespace std;
char s1[maxn],s2[maxn*2];
int n,mr,mid,r[maxn*2],ans;
int check(int x,int y)
{
    while(s2[x-y]==s2[x+y])y++;
    return y-1;
}
int main()
{
    scanf("%s",s1+1);
    n=strlen(s1+1);
    s2[0]=B,s2[n*2+2]=C; 
    for(int i=1;i<=n*2+1;i++)
    {
        if(i&1)s2[i]=A;
        else s2[i]=s1[i/2];
    }n=n*2+2;
    mr=mid=0;
    for(int i=1;i<=n;i++)
    {
        if(i>=mr)
            r[i]=check(i,1);
        else
            r[i]=check(i,min(r[mid*2-i],mr-i));
        if(r[ans]<r[i])
            ans=i;
        if(i+r[i]>mr){mid=i;mr=i+r[i];}
    }
    printf("%d",r[ans]);
    return 0;
}
//Shing has healthy hands.
並不對勁的manacher

並不對勁的manacher算法