zoukankan      html  css  js  c++  java
  • 后缀自动机五·重复旋律8

     
      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int maxn = 100010;
      4 
      5 char s[maxn], p[maxn<<1];
      6 int maxlen[maxn<<1], minlen[maxn<<1], tr[maxn<<1][26], link[maxn<<1];
      7 int green[maxn<<1], ind[maxn<<1];
      8 int sz;
      9 int news(int maxl, int minl, int *trans, int lk){
     10     link[sz] = lk; maxlen[sz] = maxl, minlen[sz] = minl;
     11     for(int i = 0; i < 26; i++) 
     12         if(trans == NULL) tr[sz][i] = -1;
     13         else tr[sz][i] = trans[i];
     14     return sz++; 
     15 }
     16 
     17 int add(int c, int u){
     18     c = c - 'a';
     19     int z = news(maxlen[u] + 1, -1, NULL, -1);
     20     green[z] = 1;
     21     int v = u;
     22     while(v != -1 && tr[v][c] == -1){
     23         tr[v][c] = z;
     24         v = link[v];
     25     }
     26     if(v == -1) {
     27         minlen[z] = 1;
     28         link[z] = 0;
     29         ind[0]++;
     30         return z;
     31     }
     32     int x =  tr[v][c];
     33     if(maxlen[x] == maxlen[v] + 1) {
     34         link[z] = x;
     35         ind[x]++;
     36         minlen[z] = maxlen[x] + 1;
     37         return z;
     38     }
     39     int y = news(maxlen[v] + 1, -1, tr[x], link[x]);
     40     minlen[x] = minlen[z] = maxlen[y] + 1;
     41     minlen[y] = maxlen[link[y]] + 1;
     42     link[x] = link[z] = y;
     43     ind[y] += 2;
     44     int w = v;
     45     while(w != -1 && tr[w][c] == x){
     46         tr[w][c] = y;
     47         w = link[w];
     48     }
     49     return z;
     50 }
     51 int cnt[maxn<<1];
     52 void get_cnt(){
     53     queue<int> q;
     54     for(int i = 0; i < sz; i++) if(ind[i] == 0) q.push(i);
     55     while(!q.empty()){
     56         int u = q.front(); q.pop();
     57         if(green[u]) cnt[u]++;
     58         cnt[link[u]] += cnt[u];
     59         if(--ind[link[u]] == 0) q.push(link[u]);
     60     }
     61 }
     62 int vis[maxn<<1];
     63 int solve(char *p){
     64     memset(vis, 0, sizeof vis);
     65     int ls = strlen(p);
     66     int len = ls / 2 + 1;
     67     int res = 0;
     68     int u = 0, l = 0;
     69     for(int i = 0; i < ls; i++){
     70         int c = p[i] - 'a';
     71         while(u && tr[u][c] == -1){
     72             u = link[u];
     73             l = maxlen[u];
     74         }
     75         if(tr[u][c] != -1){
     76             u = tr[u][c];
     77             l++;
     78         }else{
     79             u = 0; l = 0;
     80         }
     81         if(l > len){
     82             while(maxlen[link[u]] >= len){
     83                 u = link[u]; 
     84                 l = maxlen[u];
     85             }
     86         }
     87         if(l >= len && !vis[u]){
     88             vis[u] = 1;
     89             res += cnt[u];
     90         }
     91     }
     92     return res;
     93 }
     94 int main(){
     95     int n;
     96     while(scanf("%s", s) != EOF){
     97         memset(ind, 0, sizeof ind);
     98         memset(cnt, 0, sizeof cnt);
     99         memset(green, 0, sizeof green);
    100         sz = 0;
    101         int pre = news(0, 0, NULL, -1);
    102         int len = strlen(s);
    103         for(int i = 0; i < len; i++) {
    104             pre = add(s[i], pre);
    105         }
    106         get_cnt();
    107         scanf("%d", &n);
    108         for(int i = 0; i < n; i++){
    109             scanf("%s", p);
    110             len = strlen(p);
    111             int len2 = len * 2 - 1;
    112             for(int j = len; j < len2; j++){
    113                 p[j] = p[j - len];
    114             }
    115             p[len2] = '';
    116             printf("%d
    ", solve(p));
    117         }
    118     }
    119     return 0;
    120 }
    View Code
  • 相关阅读:
    整数反转
    最长公共前缀
    罗马数字转整数
    单点登录
    VMware Workstation虚拟机密钥
    Pytest 用例内部执行顺序
    判断是不是回文数
    python端口IP字符串是否合法
    python求二叉树深度
    有两个字符串类型的数字,实现一个方法将它们进行相加,并返回相加后的数值。
  • 原文地址:https://www.cnblogs.com/yijiull/p/8516318.html
Copyright © 2011-2022 走看看