回文ツリー学習ノート(テンプレート)

6890 ワード


 
回文樹をよく理解しました.
理解した后の感じ:どうして前にとても复雑だと感じますか?Orz
 
自分の理解に基づいて自分が読めるテンプレートを変更しました.
 
#include
using namespace std;
const int maxn=1e5+50;

int last,tot,n;
int next[maxn][27],len[maxn],fail[maxn],s[maxn],cnt[maxn]; 
/*
n         
last                      1  
next[i][j]   i        x                
len[i]  i            
fail[i]    i             
s[i]       i    
cnt[i]  i                       
*/
inline void init()
{
    s[0]=-1;fail[0]=1;last=0;
    len[0]=0;len[1]=-1;tot=1;
}
/*
              1     1        len[1]=1;
       :
         (  2)             :-1+2=1
*/
inline int getfail(int x,int id)
{
    while(s[id-len[x]-1]!=s[id])x=fail[x];
    return x;
}
/*
 x                               
             
    ,      1                      1    
len[1]=-1   
                1     :
(s[id-len[1]-1]=s[id-(-1)-1])==s[id] 
*/ 
inline int newnode(int x)
{
    len[++tot]=x;
    return tot;
}
inline int solve()
{
    int i,p,q;
    init();
    for(i=1;i<=n;i++)
    {
        p=getfail(last,i);
        //          s[i]               p 
        if(next[p][s[i]]==0)//   p         s[i]    
        {
            printf("%d %d ",i,q);
            q=newnode(len[p]+2);//     p     s[i]
            fail[q]=next[getfail(fail[p],i)][s[i]];
            //q         p         s[i]         s[i]               0
            next[p][s[i]]=q;
            
            for(int j=i-len[q]+1;j<=i;j++)printf("%c",s[j]+'a');
            putchar(10);
        }
        last=next[p][s[i]];//            
        cnt[next[p][s[i]]]++;//          +1 
    }
    for(i=tot;i>1;i--)
    {
        cnt[fail[i]]+=cnt[i];
        /*
        i                
                          
                                      
        */ 
    }
}
int main()
{
    char s1[maxn];
    scanf("%s",s1);
    n=strlen(s1);
    for(int i=1;i<=n;i++)s[i]=s1[i-1]-'a';
    solve();
}

 
2019-09-10 22:39:54