洛谷 P3649 [APIO2014]迴文串(迴文樹)

題目鏈接:https://www.luogu.org/problem/P3649

迴文樹的作用:

  1. 求串S前綴0~i內本質不同迴文串的個數
  2. 求串S內每一個本質不同迴文串出現的次數
  3. 求串S內迴文串的個數(其實就是1和2結合起來)
  4. 求以下標i結尾的迴文串的個數
    #include<bits/stdc++.h>
    #define M 300010
    using namespace std;
    char S[M];
    int tot,last;
    struct plalindrome_tire
    {
        int len,fail,cnt,ch[26];
        //fail指向最長後綴迴文,len當前點構成最長迴文長度,cnt迴文出現次數,ch樹的節點a~z
    } T[M];
    int get_fail(int x,int n)//返回與點n構成最長迴文的位置
    {
        while(S[n-T[x].len-1]!=S[n]) x=T[x].fail;
        return x;
    }
    int main()
    {
        scanf("%s",S+1);
        //初始化
        T[0].len=0,T[1].len=-1;
        T[0].fail=1;
        tot=1,last=0;
        for(int i=1; S[i]; ++i)
        {
            int id=S[i]-'a';
            int cur=get_fail(last,i);
            if(!T[cur].ch[id])
            {
                int v=++tot;
                T[v].len=T[cur].len+2;
                T[v].fail=T[get_fail(T[cur].fail,i)].ch[id];
                T[cur].ch[id]=v;
            }
            last=T[cur].ch[id];
            T[last].cnt++;
        }
        long long ans=0;
        for(int i=tot; i; --i)//最長迴文中還有迴文,需要從葉子節點倒着加回去,計算所有迴文串個數
        {
            T[T[i].fail].cnt+=T[i].cnt;
            ans=max(ans,1ll*T[i].len*T[i].cnt);
        }
        printf("%lld\n",ans);
    }
    

     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章