• 字符串小结-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
    ",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
    ",cas,ans);
    88     }
    89 }
    View Code
  • 相关阅读:
    Problem: 数字的拆分之二
    Problem: 数字的拆分之一
    Problem : [Usaco2014 Dec]Piggy Back
    Problem: 八中厕所的门
    Problem : [Usaco2007 Open]Catch That Cow 抓住那只牛
    vim设置
    生活致富靠传销?北海警方:排版错误已整改
    SpringBoot(二)——配置文件
    SpringBoot(一)——IDEA创建项目
    Redis(一)——安装与使用
  • 原文地址:https://www.cnblogs.com/HITLJR/p/7687872.html
Copyright © 2020-2023  润新知