回文树

求0->i内所有的本质不同的回文串的个数, 在 if(!next[cur][ch])  成立,那么说明出现本质不同的字符串

求每一个本质不同的回文串出现的个数,每个结点都是本质不同的字符串,  cnt记录的就是了

求s内回文串的个数,所有的cnt加起来就是了。

求以i结尾的回文串的个数。 num函数就是了。

 1 struct PTtree
 2 {
 3     int next[N][M];
 4     int fail[N];
 5     int len[N];//len[i]表示结点i表示的回文串的长度
 6     int cnt[N];
 7     int num[N];//num[i]存放以i结尾的回文串的个数
 8     int S[N];
 9     int last,n,p;
10     int newNode(int length)
11     {
12         for(int i=0;i<M; ++i) next[p][i] = 0;
13         num[p] = 0;
14         cnt[p] = 0;
15         len[p] = length;
16         return p++;
17     }
18     void init()
19     {
20         p = 0;
21         newNode(0);
22         newNode(-1);
23         last = 0;
24         n = 0;
25         S[n] = -1;
26         fail[0] = 1;
27         fail[1] = 0;
28     }
29 
30     int getFail(int cur)
31     {//如果S[n-len[x]-1]==S[n]那么说明结点x添加新字符后,前面也有一个字符与x相同
32         while(S[n-len[cur]-1] != S[n]) 
33             cur = fail[cur];//跳到更短一点的回文后缀节点
34         return cur;
35     }
36     void add(int ch)
37     {
38         ch -= 'a';
39         S[++n] = ch;
40         int cur = getFail(last);
41         if(!next[cur][ch])//这个回文串没有出现过
42         {
43             ans++;
44             int now = newNode(len[cur]+2);
45             fail[now] = next[getFail(fail[cur])][ch];
46             next[cur][ch] = now;
47             num[now] = num[fail[now]] + 1;//+1是为当前的回文串,num[fail[now]] 
48                                     //是更短的回文后缀的个数,与字典树的统计是一样的
49         }
50         last = next[cur][ch];
51         cnt[last]++;
52     }
53     void count()
54     {
55         //逆向是为了避免重复计算
56         for(int i=p-1;i>=0;--i)cnt[fail[i]] += cnt[i];//fail[i]是i是后缀,所以i肯定保护fail[i]
57     }
58 };
原文地址:https://www.cnblogs.com/justPassBy/p/4807932.html