zoukankan      html  css  js  c++  java
  • 【AC自动机/fail树】BZOJ3172- [Tjoi2013]单词

    【题目大意】

    http://www.lydsy.com:808/JudgeOnline/problem.php?id=3172

    某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。

    【思路】

    第一次写fail树。首先建立AC自动机,对于路径上的每一个点sum++,表示出现的次数。fail指针指向的后缀,如果从fail指针指向的点开始方向建立fail树,其子树的sum之和就等于以它作为后缀的串的总数,相当于它在文章中出现的个数。

    *fail树好神奇啊,不过E数组到底应该开多大呢?struct类型的数组到底应该怎么计算空间呢?困惑。

    【错误名】

    AC自动机的fail指针建立错了…详细见注释。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #include<queue>
      7 #define Lnum 26
      8 using namespace std;
      9 const int MAXN=201;
     10 const int MAXLEN=1000001; 
     11 int n;
     12 int cnt=0; 
     13 struct ACauto
     14 {
     15     ACauto* next[Lnum];
     16     ACauto* fail;
     17     int id,sum;
     18     ACauto()
     19     {
     20         for (int i=0;i<Lnum;i++) next[i]=NULL;
     21         fail=NULL;
     22         sum=0;
     23         id=++cnt;
     24     }
     25 };
     26 ACauto* rt=new ACauto();
     27 ACauto* node[MAXN];
     28 struct edge
     29 {
     30     ACauto* to;
     31     edge* next;
     32     edge()
     33     {
     34         to=NULL;
     35         next=NULL;
     36     }
     37 };
     38 edge* E[MAXLEN*Lnum];
     39 
     40 void addedge(ACauto* u,ACauto* v)
     41 {
     42     edge* tmp=new edge;
     43     tmp->to=v;
     44     tmp->next=E[u->id];
     45     E[u->id]=tmp;
     46 }
     47 
     48 void insert(ACauto* rt,char* str,int order)
     49 {
     50     ACauto* tmp=rt;
     51     int len=strlen(str);
     52     for (int i=0;i<len;i++)
     53     {
     54         int index=str[i]-'a';
     55         if (tmp->next[index]==NULL)
     56             tmp->next[index]=new ACauto();
     57         tmp=tmp->next[index];
     58         tmp->sum++;
     59     }
     60     node[order]=tmp;
     61 }
     62 
     63 void build(ACauto* rt)
     64 {
     65     queue<ACauto*> que;
     66     que.push(rt);
     67     while (!que.empty())
     68     {
     69         ACauto* head=que.front();que.pop();
     70         for (int i=0;i<Lnum;i++)
     71         {
     72             if (head->next[i]!=NULL)
     73             {
     74                 if (head==rt)
     75                 {
     76                     head->next[i]->fail=rt;
     77                     addedge(rt,head->next[i]);
     78                 }
     79                 else
     80                 {
     81                     ACauto* tmp=head->fail;
     82                     while (tmp!=NULL)
     83                     {
     84                         if (tmp->next[i]!=NULL)
     85                         {
     86                             head->next[i]->fail=tmp->next[i];
     87                             //指向最长的后缀,所以是tmp->next[i],而不是tmp 
     88                             addedge(tmp->next[i],head->next[i]);
     89                             break;
     90                         }
     91                         else tmp=tmp->fail;
     92                     }
     93                     if (tmp==NULL) 
     94                     {
     95                         head->next[i]->fail=rt;
     96                         addedge(rt,head->next[i]);
     97                     }
     98                 }
     99                 que.push(head->next[i]);
    100             }
    101         }
    102     }
    103 }
    104 
    105 void dfs(ACauto* rt)
    106 {
    107     for (edge* i=E[rt->id];i!=NULL;i=i->next)
    108     {
    109         dfs(i->to);
    110         rt->sum+=i->to->sum;
    111     }
    112 }
    113 
    114 void init()
    115 {
    116     scanf("%d",&n);
    117     char str[MAXLEN];
    118     for (int i=0;i<n;i++)
    119     {
    120         scanf("%s",str);
    121         insert(rt,str,i);
    122     }
    123     build(rt);
    124 }
    125 
    126 void getans()
    127 {
    128     dfs(rt);
    129     for (int i=0;i<n;i++) cout<<node[i]->sum<<endl;
    130 }
    131 
    132 int main()
    133 {
    134     init();
    135     getans();
    136     return 0;
    137 }
  • 相关阅读:
    项目启动报错:No suitable driver found for jdbc:oracle:thin:@192.168.7.146:1521:oracle
    (八)Oracle学习笔记—— 触发器
    (七)Oracle学习笔记—— 游标
    spring自动装配(No qualifying bean )
    Intellij output 中文乱码
    使用Spring开发和监控线程池服务
    IDEA在编辑时提示could not autowire
    java 过滤器(Filter)与springMVC 拦截器(interceptor)的实现案例
    Java过滤器(Filter)与SpringMVC拦截器(Interceptor)之间的关系与区别
    idea 添加多模块项目
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5380725.html
Copyright © 2011-2022 走看看