Panlindromic Tree(回文树)的四个例题

http://www.tsinsen.com/new/A1280 

双回文串,正着做一遍,倒着做一遍,维护每个节点 向前向后的最长回文子串长度(len[ last ])

 1 #include <bits/stdc++.h>
 2 const long long mod = 1e9+7;
 3 const double ex = 1e-10;
 4 #define inf 0x3f3f3f3f
 5 using namespace std;
 6 const int MAXN = 212345;
 7 const int N = 26;
 8 struct Palindromic_Tree{
 9     int next[MAXN][N];
10     int fail[MAXN];
11     int cnt[MAXN];
12     int num[MAXN];
13     int len[MAXN];
14     int S[MAXN];
15     int last;
16     int n;
17     int p;
18     int newnode(int l){
19         for (int i = 0 ; i<N; i++) next[p][i] = 0;
20         cnt[p] = 0;
21         num[p] = 0;
22         len[p] = l;
23         return p++;
24     }
25     void init(){
26         p = 0;
27         newnode(0);
28         newnode(-1);
29         last = 0;
30         n  = 0;
31         S[n] = -1;
32         fail[0] = 1;
33     }
34     int get_fail(int x){
35         while (S[n-len[x]-1] != S[n]) x = fail[x];
36         return x;
37     }
38     int add(int c){
39         c-='a';
40         S[++n] = c;
41         int cur = get_fail(last);
42         if (!next[cur][c]){
43             int now = newnode(len[cur] + 2);
44             fail[now] = next[get_fail(fail[cur])][c];
45             next[cur][c] = now;
46             num[now] = num[fail[now]] + 1;
47         }
48         last = next[cur][c];
49         cnt[last]++;
50         return len[last];
51     }
52     void count(){
53         for (int i = p-1  ; i >= 0; i--) cnt[fail[i]] += cnt[i];
54     }
55 };
56 Palindromic_Tree a;
57 int len[212345];
58 int main()
59 {
60     string s;
61     cin >> s;
62     int l = s.length();
63     a.init();
64     for (int i = 0 ; i<l ; i++){
65         len[i] = a.add(s[i]);
66     }
67     a.init();
68     int ans = 0;
69     for (int i = l-1; i>=1 ;i--){
70         ans = max(ans , len[i-1] + a.add(s[i]));
71     }
72     cout << ans << endl;
73     return 0;
74 }
View Code

http://www.tsinsen.com/new/A1255

可以把每种串的 数目和长度存下来,按照长度排个序,从大到小维护。

 1 #include <bits/stdc++.h>
 2 const long long mod = 19930726;
 3 const double ex = 1e-10;
 4 #define inf 0x3f3f3f3f
 5 using namespace std;
 6 const int MAXN = 2123456;
 7 const int N = 26;
 8 struct Palindromic_Tree{
 9     int next[MAXN][N];
10     int fail[MAXN];
11     int cnt[MAXN];
12     int num[MAXN];
13     int len[MAXN];
14     int S[MAXN];
15     int last;
16     int n;
17     int p;
18     int newnode(int l){
19         for (int i = 0 ; i<N; i++) next[p][i] = 0;
20         cnt[p] = 0;
21         num[p] = 0;
22         len[p] = l;
23         return p++;
24     }
25     void init(){
26         p = 0;
27         newnode(0);
28         newnode(-1);
29         last = 0;
30         n  = 0;
31         S[n] = -1;
32         fail[0] = 1;
33     }
34     int get_fail(int x){
35         while (S[n-len[x]-1] != S[n]) x = fail[x];
36         return x;
37     }
38     void add(int c){
39         c-='a';
40         S[++n] = c;
41         int cur = get_fail(last);
42         if (!next[cur][c]){
43             int now = newnode(len[cur] + 2);
44             fail[now] = next[get_fail(fail[cur])][c];
45             next[cur][c] = now;
46             num[now] = num[fail[now]] + 1;
47         }
48         last = next[cur][c];
49         cnt[last]++;
50     }
51     void count(){
52         for (int i = p-1  ; i >= 0; i--) cnt[fail[i]] += cnt[i];
53     }
54 };
55 Palindromic_Tree a;
56 int len[212345];
57 typedef pair<int,long long> pii;
58 pii p[1000022];
59 long long ksm(long long x,long long y){
60     long long ans = 1;
61     while (y){
62         if (y % 2) ans = ans * x % mod;
63         x = x*x % mod;
64         y/=2;
65     }
66     return ans;
67 }
68 int main()
69 {
70     string s;
71     int l;
72     long long k;
73     cin >> l >> k;
74     cin >> s;
75     a.init();
76     for (int i = 0 ; i<l ; i++){
77         a.add(s[i]);
78     }
79     a.count();
80     int cnt = 0;
81     for (int i = 2 ; i<a.p ; i++){
82         if (a.len[i] % 2 == 0) continue;
83         p[cnt++] = make_pair(a.len[i],(long long)a.cnt[i]);
84     }
85     sort(p,p+cnt);
86     long long ans = 1;
87     int i = cnt-1;
88     while (k > 0 && i >= 0){
89         ans = (ans * ksm((long long)p[i].first,min(p[i].second,k))) % mod;
90         k -= min(k,p[i].second);
91         i--;
92     }
93     if (k > 0){
94         puts("-1");
95     }
96     else cout << ans << endl;
97 }
View Code

http://www.tsinsen.com/new/A1393

这个题还是CF的17E,貌似回文树不是正解,可能需要马拉车优雅的过,明天学学马拉车写了他吧。

这个题,第一次理解了num的含义,num记录的是每一类回文串的①性质不同,②结尾相同(左对齐)的子串数目。

其中限制条件 性质不同  可以有多种理解,他们 长度 不同 且 左对齐,显然他们性质不同

另外还有,以某个节点为 右端点的所有回文子串 肯定 性质不同。

让求相交的回文串对数 , 可以 反着求,求出总的对数,减去不相交的即可。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <string>
 4 #include <algorithm>
 5 #include <iostream>
 6 const long long mod = 51123987;
 7 const double ex = 1e-10;
 8 #define inf 0x3f3f3f3f
 9 using namespace std;
10 const int MAXN = 2000009;
11 const int N = 26;
12 struct Palindromic_Tree{
13     int next[MAXN][N];
14     int fail[MAXN];
15     int cnt[MAXN];
16     int num[MAXN];
17     int len[MAXN];
18     short S[MAXN];
19     int last;
20     int n;
21     int p;
22     int newnode(int l){
23         for (int i = 0 ; i<N; i++) next[p][i] = 0;
24         cnt[p] = 0;
25         num[p] = 0;
26         len[p] = l;
27         return p++;
28     }
29     void init(){
30         p = 0;
31         newnode(0);
32         newnode(-1);
33         last = 0;
34         n  = 0;
35         S[n] = -1;
36         fail[0] = 1;
37     }
38     int get_fail(int x){
39         while (S[n-len[x]-1] != S[n]) x = fail[x];
40         return x;
41     }
42     int add(int c){
43         c-='a';
44         S[++n] = c;
45         int cur = get_fail(last);
46         if (!next[cur][c]){
47             int now = newnode(len[cur] + 2);
48             fail[now] = next[get_fail(fail[cur])][c];
49             next[cur][c] = now;
50             num[now] = num[fail[now]] + 1;
51         }
52         last = next[cur][c];
53         cnt[last]++;
54         return num[last];
55     }
56     long long count(){
57         for (int i = p-1  ; i >= 0; i--) cnt[fail[i]] += cnt[i];
58         long long ans = 0;
59         for (int i = 2 ; i<p;i++)
60             ans = (ans + cnt[i])% mod;
61         return ans;
62     }
63 };
64 Palindromic_Tree a;
65 int sum[2000009];
66 int main()
67 {
68     string s;
69     int l;
70     cin >> l;
71     cin >> s;
72     a.init();
73     for (int i = 0 ; i<l ; i++){
74         sum[i] = a.add(s[i]);
75     }
76     for (int i = 1 ; i<l ;i++){
77         sum[i] = (sum[i] + sum[i-1]) % mod;
78     }
79     long long ans = a.count();
80     ans = ans * (ans - 1 ) / 2 % mod;
81     a.init();
82     for (int i = l-1; i>0 ; i--){
83         long long x = a.add(s[i]);
84         ans = ((ans - x * sum[i-1]) % mod + mod) % mod;
85     }
86     cout << ans << endl;
87     return 0;
88 }
View Code

卡内存卡到死,CF根本过不去,tsinsen也是卡过的。

不过这个题让我深刻理解了num数组的含义

还有一题之前写过的

http://www.cnblogs.com/HITLJR/p/7687885.html

学习回文树,首先把代码看懂,找几个简单的自己模拟一下整个过程,然后理解每个数组的含义,灵活运用add的返回值求一些东西。

posted @ 2017-10-26 21:21  HITLJR  阅读(537)  评论(0编辑  收藏  举报