zoukankan      html  css  js  c++  java
  • bzoj 3172 单词 ac自动机|后缀数组

    题目大意:

    给定n个字符串连成了一篇文章,问每个字符串在这篇文章中出现的次数,可重复覆盖

    这里ac自动机和后缀数组都可以做

    当然后缀数组很容易就解决,但是相对时间消耗高

    这里就只讲ac自动机了

    将每个字符串放入ac自动机中,这里需要记录到达每个ac自动机上的节点出现这个状态有多少次

    而我们添加字符串进入的时候,应该是把经过的每个节点的val都++,说明这个字符串多出现了一次这个值

    然后因为自己用字符串在ac自动机上走肯定是到达离root最近的点,也就是说有很多的点会不断通过fail指针指向他,而这些点都是包含了这个字符串的

    那也就是说我们需要考虑 val[fail[i]] += val[i]

    这里一定是需要从最底层的点不断fail上来,我们需要找到一个合适的更新val点的顺序

    可以考虑在我们构建后缀自动机的时候我们采用的是利用队列bfs的过程,那也就是说进入的点是符合最大长度从小到大的性质的

    而fail指向的总是比它长度更小的点,所以根据进入队列的点的逆顺序来更新val即可

    也就是每次点进队列都 que[cnt++] = u;

    最后

    for(int i=sz-1 ; i>0 ; i--)
      val[fail[que[i]]]+=val[que[i]];

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <vector>
     5 #include <iostream>
     6 #include <algorithm>
     7 #include <map>
     8 using namespace std;
     9 #define clr(x) memset(x , 0 , sizeof(x))
    10 #define set(x) memset(x , -1 , sizeof(x))
    11 typedef long long LL ;
    12 
    13 const int CHAR_SIZE = 26;
    14 const int MAX_SIZE = 1000005;
    15 const int M = 10000 ;
    16 
    17 struct AC_Machine{
    18     int ch[MAX_SIZE][CHAR_SIZE] , val[MAX_SIZE] , fail[MAX_SIZE] , que[MAX_SIZE];
    19     int sz;
    20     bool vis[MAX_SIZE];
    21     void init(){
    22         sz = 1;
    23         clr(ch[0]) , clr(val) , clr(vis);
    24     }
    25 
    26     int insert(string s){
    27         int n = s.length();
    28         int u=0 ;
    29         for(int i=0 ; i<n ; i++){
    30             int c = s[i]-'a';
    31             if(!ch[u][c]){
    32                 clr(ch[sz]) , val[sz]=0;
    33                 ch[u][c] = sz++;
    34             }
    35             u = ch[u][c];
    36             val[u]++;
    37         }
    38         return u;
    39     }
    40 
    41     void get_fail(){
    42         queue<int> Q;
    43         fail[0] = 0;
    44         int cnt = 0;
    45         for(int c=0 ; c<CHAR_SIZE ; c++){
    46             int u = ch[0][c];
    47             if(u){Q.push(u);fail[u]=0,que[cnt++]=u;}
    48         }
    49         while(!Q.empty()){
    50             int r = Q.front();
    51             Q.pop();
    52             for(int c=0 ; c<CHAR_SIZE ; c++){
    53                 int u = ch[r][c];
    54                 if(!u){ch[r][c] = ch[fail[r]][c]; continue;}
    55                 fail[u] = ch[fail[r]][c];
    56                 Q.push(u);
    57                 que[cnt++]=u;
    58             }
    59         }
    60     }
    61     void updateVal(){
    62         for(int i=sz-1 ; i>0 ; i--)
    63             val[fail[que[i]]]+=val[que[i]];
    64     }
    65 }ac;
    66 int n , pos[205];
    67 string s[205];
    68 
    69 int main()
    70 {
    71    // freopen("a.in" , "r" , stdin);
    72    // freopen("out.txt" , "w" , stdout);
    73     scanf("%d" , &n);
    74     ac.init();
    75     for(int i=0 ; i<n ; i++){
    76         cin>>s[i];
    77         pos[i] = ac.insert(s[i]);
    78     }
    79     ac.get_fail();
    80     ac.updateVal();
    81     for(int i=0 ; i<n ; i++)
    82         printf("%d
    " , ac.val[pos[i]]);
    83     return 0;
    84 }
  • 相关阅读:
    Android 图片处理之 Fresco
    Android数据列表展示之 RecylerView
    新浪微博第二天
    Android之MVP设计模式
    android中fragment与activity之间通信原理以及例子
    SpannableString设置文本背景色
    新浪微博应用第一天
    python D11 迭代及闭包
    python D10 函数进阶
    python D9 初识函数
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/5155367.html
Copyright © 2011-2022 走看看