zoukankan      html  css  js  c++  java
  • POJ2222 Keywords Search AC自动机模板

    题意:给出一些单词,求多少个单词在字符串中出现过(单词表单词可能有相同的,这些相同的单词视为不同的分别计数)(如果单词x在字符串中出现一次而在单词表中有两个则ans+2,在字符串中出现两次而单词表中有一个则ans+1)
    AC自动机模板题,之前学了总觉得不扎实,现在有底了现在终于可以去敲心头大恨,兴奋!!!
    代码
     1 #include<cstdio>
     2 #include<cstring>
     3 const int maxn=10010;
     4 const double eps=1e-8;
     5 const long long modn=1000;
     6 int n;
     7 char a[51]={};
     8 char b[100*maxn]={};
     9 struct trie{
    10     int next[26];
    11     bool exist;
    12     int count;
    13     int fail;
    14 }e[maxn*50]={};
    15 int tot,ans;
    16 int q[maxn*50]={};
    17 
    18 void init(int x,int k,int j){
    19     if(j>k){ 
    20         e[x].exist=1;
    21         e[x].count++;
    22         return; 
    23     }
    24     int z=a[j]-'a';
    25     if(!e[x].next[z])
    26         e[x].next[z]=++tot;
    27     init(e[x].next[z],k,j+1);
    28 }
    29 void fir(){
    30     memset(e,0,sizeof(e)); memset(q,0,sizeof(q));
    31     tot=ans=0;
    32 }
    33 void doit(){
    34     int head=0,tail=0,x,y,f;
    35     q[0]=0;
    36     while(head<=tail){
    37         x=q[head++];
    38         for(int i=0;i<26;i++){
    39             if(e[x].next[i]){
    40                 y=e[x].next[i];
    41                 if(x!=0){
    42                     f=e[x].fail;
    43                     while((!e[f].next[i]) && f )
    44                         f=e[f].fail;
    45                     e[y].fail=e[f].next[i];
    46                 }q[++tail]=y;
    47             }
    48         }
    49     }
    50 }
    51 void find(){
    52     scanf("%s",&b);
    53     int k=std::strlen(b);
    54     int x=0,z,y;
    55     for(int i=0;i<k;i++){
    56         z=b[i]-'a';
    57         while( (!e[x].next[z])&& x){
    58             x=e[x].fail;
    59         }x=e[x].next[z]; y=x;
    60         while(y&&e[y].count){
    61             ans+=e[y].count;
    62             e[y].count=0;
    63             y=e[y].fail;
    64         }
    65     }
    66 }
    67 int main(){
    68     int T;scanf("%d",&T);
    69     while(T-->0){
    70         fir();
    71         scanf("%d",&n);
    72         for(int i=1;i<=n;i++){ 
    73             scanf("%s",&a);
    74             init(0,std::strlen(a)-1,0); 
    75         }
    76         doit();
    77         find();
    78         printf("%d
    ",ans);
    79     }
    80     return 0;
    81 }
    View Code

     更新:

    整理模板的时候发现自己原来的代码有问题。这个新版本应该没问题了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 using namespace std;
     8 const int maxn=10100;
     9 int n,siz;
    10 char ch[60]={};
    11 char str[maxn*100]={};
    12 struct trie{
    13     int sig[26];
    14     int cnt;
    15     int vis;
    16     int fail;
    17 }t[maxn*60];int tot=0;
    18 int q[maxn*60]={};int head=0,tail=0;
    19 void fir(){
    20     tot=0;memset(t,0,sizeof(t));//memset(q,0,sizeof(q));
    21 }
    22 void init(int x,int j){
    23     if(j>siz-1){ t[x].cnt++; return; }
    24     int z=ch[j]-'a';
    25     if(!t[x].sig[z])t[x].sig[z]=++tot;
    26     init(t[x].sig[z],j+1);
    27 }
    28 void build_fail(){
    29     int head=0,tail=0,x,y,f;q[0]=0;
    30     while(head<=tail){
    31         x=q[head++];
    32         for(int i=0;i<26;i++)
    33             if(t[x].sig[i]){
    34                 y=t[x].sig[i];
    35                 if(x){
    36                     f=t[x].fail;
    37                     while((!t[f].sig[i])&&f)
    38                         f=t[f].fail;
    39                     t[y].fail=t[f].sig[i];
    40                 }q[++tail]=y;
    41             }
    42     }
    43 }
    44 int get_num(){//字符串中包含的单词数量,重复的不记录,
    45     //如果单词x在字符串中出现一次而在单词表中有两个则ans+2
    46     //在字符串中出现两次而单词表中有一个则ans+1
    47     int ans=0,x=0,y,z;
    48     for(int i=0;i<siz;i++){
    49         z=str[i]-'a';
    50         while((!t[x].sig[z])&&x)
    51             x=t[x].fail;
    52         x=t[x].sig[z];y=x;
    53         while(y&&(!t[y].vis)){//保证了每个结尾只访问一次
    54             ans+=t[y].cnt;
    55             t[y].vis=1;t[y].cnt=0;
    56             y=t[y].fail;
    57         }
    58     }
    59     return ans;
    60 }
    61 int main(){
    62     int T;scanf("%d",&T);
    63     while(T-->0){
    64         fir();
    65         scanf("%d",&n);
    66         for(int i=1;i<=n;i++){scanf("%s",ch);siz=strlen(ch);init(0,0);}
    67         build_fail();
    68         scanf("%s",str);siz=strlen(str);
    69         printf("%d
    ",get_num());
    70     }
    71     return 0;
    72 }
    new

  • 相关阅读:
    python前端之css
    前端开发
    python前端开发工具篇
    python数据结构和算法2 顺序表和链表
    python数据结构和算法3 栈、队列和排序
    python数据结构和算法 二叉树
    python数据结构和算法1
    python18天-pycharm & 正则表达式
    Head First Servlets & JSP 学习笔记 第五章 —— 作为Web应用
    Head First Servlets & JSP 学习笔记 第四章 —— 作为Servlet
  • 原文地址:https://www.cnblogs.com/137shoebills/p/7786493.html
Copyright © 2011-2022 走看看