[テンプレート] manachar

問題のクラスを解決するための馬車車のアルゴリズムは、最長の回文文字列は、時間の複雑さをするために減少させることができる\(O(N)\) ほとんど理論的下界へ。

コアアイデア:パリティサブ論じた場合は、同一の(奇数)に変換される場合。

次のポイントは、アルゴリズム記述の本質を使用する必要があります。

  1. \(P [i]は\)で表される\(Iは\)パリンドローム配列由来の半径の最長の長さの中心として、\(P [i]が-1 \ ) するために、元の文字列を表す\(Iは\)であります中央部分文字列のパリンドロームの最長。

    証明:派生文字列Tに、すべての文字列の回文の長さが奇数である場合、ATに対する(Iは\)\最長文字列パリンドロームの中心として、それは長さである\(2 * P [I] -1 \) 観察を介して他の文字より一定数を超えるセパレータの数は、ある特徴、Tパリンドロームすべてのサブストリング、見出さ\(P [i]は\)デリミタ、残り\(Pは[ i]が-1 \)元の文字列から文字、長さの元の文字列内のパリンドローム配列である\(P [I] -1 \)

  2. 文字を追加するために回文配列を計算する際にパリンドローム、元の文字列の長さが、でも答えが奇数の中心として、元の文字列である中心。

  3. \(IDの\)を中心として、\(私は\)式の対称点の座標((ID << 1)-i \ \)

  4. (それ自体を含む)のサブ通常パリンドローム配列、パリンドローム配列として\((P [I] -1 )>> 1 \)

/*
    马拉车算法模板
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn=3e7+10;
char s[maxn],str[maxn];
int n,ans,p[maxn];
void init(){
    str[0]=str[1]='#';
    for(int i=1;i<=n;i++)str[i<<1]=s[i],str[i<<1|1]='#';
    n=(n<<1)+2;str[n--]=0;
}
void manachar(){
    int id=0,mx=0;
    for(int i=1;i<=n;i++){
        p[i]=mx>i?min(mx-i,p[(id<<1)-i]):1;
        while(str[i+p[i]]==str[i-p[i]])p[i]++;
        if(i+p[i]>mx)mx=i+p[i],id=i;
    }
}
int main(){
    scanf("%s",s+1);
    n=strlen(s+1);
    init();manachar();
    for(int i=1;i<=n;i++)ans=max(ans,p[i]);
    printf("%d\n",ans-1);
    return 0;
}

おすすめ

転載: www.cnblogs.com/wzj-xhjbk/p/10991127.html