字符串小结-AC自动机+后缀数组+回文树

kmp就直接略过吧

AC自动机,后缀数组,回文树,……(后续待学)

AC自动机

模板

  1 #include <bits/stdc++.h>
  2 const long long mod = 1e9+7;
  3 const double ex = 1e-10;
  4 const int maxn = 5000005;
  5 const int maxm = 30;
  6 #define inf 0x3f3f3f3f
  7 using namespace std;
  8 int ans = 0;
  9 int a[100];
 10 int T[1123456];
 11 char tc[100];
 12 char Tc[1123456];
 13 struct Trie{
 14     int ch[maxn][maxm];
 15     int last[maxn];
 16     int val[maxn];
 17     int f[maxn];
 18     int vis[maxn];
 19     int sz;
 20     Trie() {
 21         sz = 1;
 22         for (int i = 0; i<maxm ; i++)
 23             ch[0][i] = 0;
 24     }
 25     void init(){
 26         for (int i = 0; i<=1; i++){
 27             for (int j = 0 ; j < maxm ; j++){
 28                 ch[i][j] = 0;
 29             }
 30             val[i] = 0;
 31             f[i] = 0;
 32             last[i] = 0;
 33         }
 34         sz = 1;
 35     }
 36     void insert(int l,int v){
 37         int u = 0;
 38         for (int i = 0; i<l; i++){
 39             int c = a[i];
 40             if (!ch[u][c]){
 41                 memset(ch[sz],0,sizeof(ch[sz]));
 42                 val[sz] = 0;
 43                 ch[u][c] = sz++;
 44             }
 45             u = ch[u][c];
 46         }
 47         //val[u] = v;
 48         val[u]++;
 49         vis[u] = 0;
 50     }
 51     void getFail(){
 52         queue <int> q;
 53         for (int c = 0;c<maxm;c++){
 54             int u = ch[0][c];
 55             if (u){
 56                 f[u] = 0;
 57                 q.push(u);
 58                 last[u] = 0;
 59             }
 60         }
 61         while (!q.empty()){
 62             int r = q.front();q.pop();
 63             for (int c = 0;c<maxm;c++){
 64                 int u = ch[r][c];
 65                 //if (!u){
 66                 //    ch[r][c] = ch[f[r]][c];continue;
 67                 //}
 68                 if (!u) continue;
 69                 q.push(u);
 70                 int v = f[r];
 71                 while (v && !ch[v][c]) v = f[v];
 72                 f[u] = ch[v][c];
 73                 last[u] = val[f[u]] ? f[u] : last[f[u]];
 74             }
 75         }
 76     }
 77     void find(int n){
 78         int j = 0;
 79         for (int i = 0 ; i < n ;i++){
 80             int c = T[i];
 81             while (j && !ch[j][c]) j = f[j];
 82             j = ch[j][c];
 83             if (val[j] && !vis[j]) print(j);
 84             else if (last[j] && !vis[last[j]]) print(last[j]);
 85         }
 86     }
 87     void print(int j){
 88         if (j&&!vis[j]){
 89             ans+=val[j];
 90             vis[j] = 1;
 91             print(last[j]);
 92         }
 93     }
 94 
 95 }Tri;
 96 
 97 int main()
 98 {
 99     int t;
100     scanf("%d",&t);
101     while (t--){
102         int N;
103         scanf("%d",&N);
104         Tri.init();
105         for (int i = 1; i <=N; i++){
106             scanf("%s",tc);
107             int l = strlen(tc);
108             //assert(l>=51);
109             for (int j = 0 ; j < l ; j++){
110                 a[j] = tc[j]-'a';
111             }
112             Tri.insert(l,i);
113         }
114         Tri.getFail();
115         scanf("%s",Tc);
116         int l = strlen(Tc);
117         for (int j = 0 ; j < l ; j++){
118             T[j] = Tc[j]-'a';
119         }
120         ans = 0;
121         Tri.find(l);
122         printf("%d\n",ans);
123     }
124     return 0;
125 }
View Code

例题

http://www.cnblogs.com/HITLJR/p/7560161.html  2016沈阳

后缀数组

模板

 1 const int maxn = 800005;
 2 int sa[maxn],t[maxn],t2[maxn],c[maxn],n;
 3 int bb[maxn];
 4 int s[maxn];
 5 void build_sa(int m){
 6     int *x = t, *y = t2;
 7     for (int i  = 0 ; i< m ;i++) c[i] = 0;
 8     for (int i = 0 ; i < n ; i++) c[x[i] = s[i]]++;
 9     for (int i = 1;  i<m ;i++) c[i] += c[i-1];
10     for (int i = n - 1 ; i >= 0 ; i--) sa[--c[x[i]]] = i;
11     for (int k = 1; k <= n ;k<<=1){
12         int p = 0;
13         for (int i = n-k; i < n; i++) y[p++] = i;
14         for (int i = 0 ; i < n ; i++) if (sa[i] >= k ) y[p++] = sa[i] - k;
15         for (int i = 0 ; i < m ; i++) c[i] = 0;
16         for (int i = 0 ; i < n ; i++) c[x[y[i]]]++;
17         for (int i = 1 ; i < m ;i++) c[i] += c[i-1];
18         for (int  i = n - 1 ; i >= 0 ; i--) sa[--c[x[y[i]]]] = y[i];
19         swap(x,y);
20         p = 1;x[sa[0]] = 0;
21         for (int i = 1;  i < n ; i++)
22             x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1] + k] == y[sa[i] + k]?p-1:p++;
23         if (p >= n)break;
24             m = p;
25 
26     }
27 }
28 int ran[maxn],height[maxn];
29 //from 1 to n-1;
30 //sa[0] = n-1;
31 //ran[n-1] = 0; the last is 0;
32 // height 代表 和 前面的
33 void getHeight(){
34     int k = 0;
35     for (int i  = 0 ; i<n ;i++) ran[sa[i]] = i;
36     for (int i = 0; i<n ;i++){
37         if (k) k--;
38         int j = sa[ran[i]-1];
39         while (s[i+k] == s[j+k]) {k++;}
40         height[ran[i]] = k;
41     }
42 }
43 void print(){
44     for (int i = 0 ; i<=10; i++)
45         cout << sa[i] <<" ";
46     cout << endl;
47     for (int i = 0 ; i<=10; i++)
48         cout << ran[i] <<" ";
49     cout << endl;
50     for (int i = 0 ; i<=10; i++)
51         cout << height[i] <<" ";
52     cout << endl;
53 
54 }
View Code

例题:http://codeforces.com/gym/101470/attachments B题

  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 = 200005;
  7 int s[maxn];
  8 char ss[maxn];
  9 int sa[maxn],t[maxn],t2[maxn],c[maxn],n;
 10 int N,K;
 11 void build_sa(int m){
 12     int *x = t, *y = t2;
 13     for (int i = 0; i < m ; i++) c[i] = 0;
 14     for (int i = 0; i < n ; i++) c[x[i] = s[i]]++;
 15     for (int i = 1; i < m ; i++) c[i] += c[i-1];
 16     for (int i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
 17     for (int k = 1 ; k <= n ; k <<= 1){
 18         int p = 0;
 19         for (int i = n-k ; i < n ; i++) y[p++] = i;
 20         for (int i = 0; i < n ; i++) if (sa[i] >= k ) y[p++] = sa[i] - k;
 21         for (int i = 0 ; i < m ; i++) c[i] = 0;
 22         for (int i = 0 ; i < n ; i++) c[x[y[i]]]++;
 23         for (int i = 1 ; i < m ; i++) c[i] += c[i-1];
 24         for (int i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
 25         swap(x,y);
 26         p = 1;x[sa[0]] = 0;
 27         for (int i = 1 ; i < n ; i++)
 28             x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i] + k]?p-1:p++;
 29         if (p >= n) break;
 30         m = p;
 31     }
 32 }
 33 int ran[maxn],height[maxn];
 34 void getrank(){
 35     for (int i = 0 ; i < n ; i++) ran[sa[i]] = i;
 36 }
 37 bool check2(int pos,int id){
 38     int cnt = 0;
 39     //cout << pos << " "<<id <<" !" << endl;
 40     for (int i = 1; i<=K ;i++){
 41         //cout << pos <<" " << ran[pos] << endl;
 42         if (ran[pos]<=id){
 43             pos+=(N+K-1)/K;
 44             if (pos >= N) pos -= N;
 45             ++cnt;
 46         }
 47         else {
 48             if (N%K==0) return false;
 49             pos+=N/K;
 50             if (pos >= N) pos -= N;
 51         }
 52     }
 53     //cout << endl;
 54     return ((cnt) >= (N % K));
 55 }
 56 bool check(int id){
 57     for (int i = 0; i<(N+K-1)/K ; i++){
 58         if (check2(i,id)){
 59             return true;
 60         }
 61     }
 62     return false;
 63 }
 64 void print(){
 65     for (int i = 0; i<=30; i++)
 66         cout << ran[i] <<" ";
 67     cout << endl;
 68     for (int i = 0; i<=30; i++)
 69         cout << sa[i] <<" ";
 70     cout << endl;
 71     for (int i = 0; i<=30; i++)
 72         cout << height[i] <<" ";
 73     cout << endl;
 74 
 75 }
 76 int main()
 77 {
 78         freopen("B.in","r",stdin);
 79         scanf("%d%d",&N,&K);
 80         scanf(" %s",ss);
 81          for (int i = 0; i<N; i++){
 82             s[i] = ss[i] - '0';
 83         }
 84         for (int i = 0 ; i < N; i++){
 85             s[i+N] = s[i];
 86         }
 87         n = 2*N+1;
 88         s[2*N] = 0;
 89         build_sa(10);
 90         getrank();
 91 
 92         //print();
 93         int l = 0;
 94         int r = n-1;
 95         int ans = 0;
 96         int cnt = 0;
 97         while (l <= r){
 98             int mid = (l+r)/2;
 99             if (check(mid)){
100                 ans = mid;
101                 r = mid - 1;
102             }
103             else{
104                 l = mid + 1;
105             }
106         }
107         for (int j = 0 ; j < (N+K-1) / K ; j++){
108             cout << s[sa[ans]+j];
109         }
110         cout << endl;
111     return 0;
112 }
View Code

回文树

http://blog.csdn.net/u013368721/article/details/42100363

杭电大佬学习笔记

模板

 1 const int MAXN = 200022;
 2 const int N = 26;
 3 char A[200022],B[200022];
 4 struct Palindromic_Tree{
 5     int next[MAXN][N];
 6     int fail[MAXN];
 7     int cnt[MAXN];
 8     int num[MAXN];
 9     int len[MAXN];
10     int S[MAXN];
11     int last;
12     int n;
13     int p;
14     int newnode(int l){
15         for (int i = 0; i < N; i++) next[p][i] = 0;
16         cnt[p] = 0;
17         num[p] = 0;
18         len[p] = l;
19         return p++;
20     }
21     void init(){
22         p = 0;
23         newnode(0);
24         newnode(-1);
25         last  = 0;
26         n = 0;
27         S[n] = -1;
28         fail[0] = 1;
29     }
30     int get_fail(int x){
31         while (S[n - len[x] - 1] != S[n]) x=fail[x];
32         return x;
33     }
34     void add(int c){
35         c -= 'a';
36         S[++n] = c;
37         int cur = get_fail(last);
38         if (!next[cur][c]){
39             int now = newnode(len[cur] + 2);
40             fail[now] = next[get_fail(fail[cur])][c];
41             next[cur][c] = now;
42             num[now] = num[fail[now]] + 1;
43         }
44         last = next[cur][c];
45         cnt[last]++;
46     }
47     void count(){
48         for (int i = p - 1; i>=0; --i) cnt[fail[i]] += cnt[i];
49     }
50 };
51 Palindromic_Tree a,b;
View Code

例题

2014 西安 G题

就是在建好的回文树上进行DFS计数。

深刻理解了count的作用。

 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 = 200022;
 7 const int N = 26;
 8 char A[200022],B[200022];
 9 struct Palindromic_Tree{
10     int next[MAXN][N];
11     int fail[MAXN];
12     int cnt[MAXN];
13     int num[MAXN];
14     int len[MAXN];
15     int S[MAXN];
16     int last;
17     int n;
18     int p;
19     int newnode(int l){
20         for (int i = 0; i < N; i++) next[p][i] = 0;
21         cnt[p] = 0;
22         num[p] = 0;
23         len[p] = l;
24         return p++;
25     }
26     void init(){
27         p = 0;
28         newnode(0);
29         newnode(-1);
30         last  = 0;
31         n = 0;
32         S[n] = -1;
33         fail[0] = 1;
34     }
35     int get_fail(int x){
36         while (S[n - len[x] - 1] != S[n]) x=fail[x];
37         return x;
38     }
39     void add(int c){
40         c -= 'a';
41         S[++n] = c;
42         int cur = get_fail(last);
43         if (!next[cur][c]){
44             int now = newnode(len[cur] + 2);
45             fail[now] = next[get_fail(fail[cur])][c];
46             next[cur][c] = now;
47             num[now] = num[fail[now]] + 1;
48         }
49         last = next[cur][c];
50         cnt[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,b;
57 long long dfs(int x,int y){
58     long long tans = 0;
59     for (int i = 0 ; i< 26 ; i++){
60         if (a.next[x][i]&&b.next[y][i]){
61             tans += 1LL*a.cnt[a.next[x][i]]*b.cnt[b.next[y][i]] + dfs(a.next[x][i],b.next[y][i]);
62         }
63     }
64     return tans;
65 }
66 int main()
67 {
68     int T;
69     scanf("%d",&T);
70     for (int cas = 1; cas <= T; cas++){
71         scanf(" %s",A);
72         scanf(" %s",B);
73         a.init();
74         b.init();
75         int la = strlen(A);
76         int lb = strlen(B);
77         for (int i = 0 ; i < la ; i++){
78             a.add(A[i]);
79         }
80         for (int i = 0 ; i < lb ; i++){
81             b.add(B[i]);
82         }
83         a.count();
84         b.count();
85         long long ans = 0;
86         ans = dfs(0,0) + dfs(1,1);
87         printf("Case #%d: %lld\n",cas,ans);
88     }
89 }
View Code

 

posted @ 2017-10-18 17:32  HITLJR  阅读(214)  评论(0编辑  收藏  举报