P5496 [テンプレート]回文オートマトン(PAM)

免責事項:この記事はブロガーオリジナル記事です、続くBY-SAのCC 4.0を著作権契約、複製、元のソースのリンクと、この文を添付してください。
このリンク: https://blog.csdn.net/qq_43544481/article/details/102770060

タイトル説明

文字列を考えます S S 各文字が小文字であることを確認してください。各位置のためのSS、パリンドロームサブストリング位置の端への要求の数。

この文字列は、最初の文字を除いて、他の文字は、場所の答えによって復号化される必要があり、暗号化されています。

具体地,若第 1 I(私はGEQ 1 \) 答えが場所であります K K 、最初の + 1 I + 1 文字が読み込ま A S C ASCII コード C C 、サブセクション + 1 I + 1 文字の本当の A S C ASCII コード C - 97 + K メートル インクルード D 26 + 97 (C-97 + K)\方法26 + 97 暗号化の前と後のすべての文字はすべて小文字です。

入力形式

文字列のライン S S 文字列が暗号化されて表しています。

出力フォーマット

ライン、 | S | |よ| 整数。最初の 整数最初に元の文字列を表します。 サブストリング回文の最後の文字の数。

回文ツリーテンプレートのタイトルが、力によって、私たちは、パリンドローム配列番号kの前面を使用する必要があります

#include<bits/stdc++.h>
using namespace std;
const int MAXNODE = 6e5+50;
const int MOD = 1e9+7;
struct Palindrome{
    int nxt[MAXNODE][26],fail[MAXNODE],len[MAXNODE],cnt[MAXNODE];
    int sz,last,sn;
    char s[MAXNODE];
    Palindrome(){
        len[0]=0,len[1]=-1;
        fail[0]=1,fail[1]=0;
        last = sn = 0,sz = 1;
        s[0] = '#';//将第一个字符表示成字符串中没出现过的字符
    }
    int Build(char ch){
        s[++sn] = ch;
        int root = last;
        while(s[sn-len[root]-1]!=ch)
            root = fail[root];
        if(!nxt[root][ch-'a']){
            len[++sz] = len[root] + 2;
            int tmp = fail[root];
            while(s[sn-len[tmp]-1]!=ch)
                tmp = fail[tmp];
            fail[sz] = nxt[tmp][ch-'a'];
            cnt[sz] = cnt[fail[sz]] + 1;
            nxt[root][ch-'a'] = sz;
        }
        last = nxt[root][ch-'a'];
        return cnt[last];
    }
}PAM;
char str[MAXNODE];
int main(){
    scanf("%s",str);
    int len = strlen(str);
    for(int i=0,k=0;i<len;i++){
        str[i] = (str[i]-97+k)%26+97;
        k = PAM.Build(str[i]);
        printf("%d ",k);
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/qq_43544481/article/details/102770060