zoukankan      html  css  js  c++  java
  • AC自动机入门经典题目(两种表达方式)

    Keywords Search

    指针方式:

      1 /* Keywords Search */
      2 # include <iostream>
      3 # include <stdio.h>
      4 # include <string.h>
      5 # include <string>
      6 # include <cstdlib>
      7 # include <ctime>
      8 # include <cmath>
      9 # include <cctype>
     10 # include <vector>
     11 # include <deque>
     12 # include <queue>
     13 # include <stack>
     14 # include <climits>
     15 # include <bitset>
     16 # include <set>
     17 # include <map>
     18 using namespace std;
     19 
     20 # define N 1001000
     21 # define INF 0x3f3f3f3f
     22 # define lowbit(x)(x&(-x))
     23 
     24 struct node
     25 {
     26     int cnt;
     27     node *next[26];
     28     node *fail;
     29     node(){
     30             cnt=0;
     31             fail=NULL;
     32             memset(next, NULL, sizeof(next));
     33     }
     34 };
     35 node *root;
     36 char s[55], str[N];
     37 int n;
     38 
     39 void init()
     40 {
     41     root = new node;
     42 }
     43 
     44 void _Insert(char *ss)
     45 {
     46     int len = strlen(ss);
     47     node *p=root;
     48     for(int i=0; i<len; i++ )
     49     {
     50         int t=ss[i]-'a';
     51         if( p->next[t]==NULL )
     52             p->next[t]=new node;
     53         p=p->next[t];
     54     }
     55    p->cnt++;
     56 }
     57 
     58 void Build_the_fail()
     59 {
     60     root -> fail = NULL;
     61     //node *p=root;
     62     queue<node*>q;
     63     q.push(root);
     64 
     65     while( !q.empty() )
     66     {
     67         node *cur=q.front();
     68         q.pop();
     69 
     70         for(int i=0; i<26; i++ )
     71         {
     72             if( cur->next[i]!=NULL )
     73             {
     74                 if( cur==root )
     75                     cur->next[i]->fail = root;
     76                 else
     77                 {
     78                     node *p=cur->fail;
     79                     while( p!=NULL )
     80                     {
     81                         if( p->next[i]!=NULL )
     82                         {
     83                             cur->next[i]->fail = p->next[i];
     84                             break;
     85                         }
     86 
     87                         else
     88                         {
     89                             p = p -> fail;
     90                         }
     91                     }
     92                     if( p==NULL )
     93                         cur->next[i]->fail = root;
     94                 }
     95                 q.push(cur->next[i]);
     96             }
     97         }
     98     }
     99 }
    100 
    101 int query(char *str)
    102 {
    103     node *cur=root;
    104     int pos;
    105     int cont=0;
    106     int len=strlen(str);
    107     for(int i=0; i<len; i++ )
    108     {
    109         pos=str[i]-'a';
    110         while( cur->next[pos]==NULL && cur!=root )
    111         {
    112             cur = cur->fail;
    113         }
    114         cur = cur->next[pos];
    115         if( cur==NULL )
    116             cur = root;
    117         node *temp=cur;
    118         while( temp!=root )
    119         {
    120             if( temp->cnt!=-1 )
    121             {
    122                 cont += temp-> cnt;
    123                 temp -> cnt = -1;
    124             }
    125             temp = temp -> fail;
    126         }
    127     }
    128     return cont;
    129 }
    130 
    131 int main()
    132 {
    133     int t;
    134     scanf("%d", &t);
    135     while( t-- )
    136     {
    137         init();
    138         scanf("%d", &n);
    139         for(int i=0; i<n; i++ )
    140         {
    141             scanf("%s", s);
    142             _Insert(s);
    143         }
    144         Build_the_fail();
    145         scanf("%s", str);
    146         printf("%d
    ", query(str));
    147     }
    148     return 0;
    149 }
    View Code

     数组方式:

      1 /* */
      2 # include <iostream>
      3 # include <algorithm>
      4 # include <utility>
      5 # include <memory>
      6 # include <deque>
      7 # include <queue>
      8 # include <stack>
      9 # include <map>
     10 # include <set>
     11 # include <list>
     12 # include <vector>
     13 # include <cassert>
     14 # include <functional>
     15 # include <bitset>
     16 # include <cmath>
     17 # include <cstdlib>
     18 # include <climits>
     19 # include <cstring>
     20 # include <string>
     21 using namespace std;
     22 typedef long long ll;
     23 
     24 # define mem(a,b)(a,b,sizeof(a))
     25 # define lowbit(x)(x&(-x))
     26 # define lcm(a,b)(a*b/__gcd(a,b))
     27 const ll mod=1e9+7;
     28 const int maxn=500010;
     29 const double pi=acos(-1.0);
     30 
     31 struct ac_auto
     32 {
     33     int Next[maxn][26], Fail[maxn], End[maxn];//Next[now][buf[i]-'a'] 是now节点存着buf[i]字符的子节点的编号
     34     int L, root;//注意这是全局变量,L是编号,root是根节点
     35 
     36 
     37     int newNode(){
     38         for(int i=0; i<26; i++ )//26叉树
     39             Next[L][i] = -1;
     40         End[L++] = 0;
     41         return L-1;//返回节点编号
     42     }
     43 
     44     void Initial(){
     45         L=0;
     46         root = newNode();
     47     }
     48 
     49     void Insert( char buf[] )
     50     {
     51         int len=strlen(buf);
     52         int now = root;
     53         for(int i=0; i<len; i++ )
     54         {
     55             if( Next[now][buf[i]-'a'] == -1 )
     56                 Next[now][buf[i]-'a'] = newNode();//若子节点没有buf[i],则插入buf[i]
     57             now = Next[now][buf[i]-'a'];//now是当前节点编号
     58         }
     59         End[now]++;//作为结束字符的编号+1,计算单词出现的次数
     60     }
     61 
     62     void Build_the_fail()
     63     {
     64         queue<int>ans;
     65         Fail[root] = root;//根节点的失败指针指向自己
     66 
     67         for(int i=0; i<26; i++ )
     68         {
     69             if( Next[root][i]==-1 )
     70                 Next[root][i] = root;
     71             else
     72             {
     73                 Fail[Next[root][i]] = root;//根节点的子节点的失败指针指向根节点
     74                 ans.push(Next[root][i]);
     75             }
     76         }
     77 
     78         while( !ans.empty() )
     79         {
     80             int now = ans.front();
     81             ans.pop();
     82 
     83             for(int i=0; i<26; i++)
     84             {
     85                 if( Next[now][i]==-1 )
     86                     Next[now][i] = Next[Fail[now]][i];//若buf[i]没有插入字典树,则将令其等于其父节点的失败指针指向的节点的子节点buf[i]字符所在的节点
     87                 else
     88                 {
     89                     Fail[Next[now][i]] = Next[Fail[now]][i];//若buf[i]已经插入,其失败指针就指向其父节点的失败指针指向的节点的子节点buf[i]所在的节点
     90                     ans.push(Next[now][i]);//
     91                 }
     92             }
     93         }
     94     }
     95 
     96     int Query( char buf[] )
     97     {
     98         int now = root;//从根节点开始找,now初始化为root
     99         int res = 0;//结果
    100         int len = strlen(buf);
    101 
    102         for(int i=0; i<len; i++ )
    103         {
    104             now = Next[now][buf[i]-'a'];//当前节点的编号
    105             int temp = now;
    106             while( temp!=root )
    107             {
    108                 res += End[temp];//只有找到单词最后一个字符所在位置End[temp]才会>0,否则为0,所以可以直接加
    109                 End[temp] = 0;//加完后置为0
    110                 temp = Fail[temp];//拓展到失败指针指向的位置,继续找
    111             }
    112         }
    113         return res;
    114     }
    115 }AC;
    116 
    117 const int MAXN = 1000010;
    118 int T, n;
    119 char buf[MAXN];
    120 
    121 int main()
    122 {
    123     ios::sync_with_stdio(false);
    124     cin>>T;
    125     while( T-- )
    126     {
    127         cin>>n;
    128         AC.Initial();
    129         for(int i=0; i<n; i++ )
    130         {
    131             cin>>buf;
    132             AC.Insert(buf);
    133         }
    134         AC.Build_the_fail();
    135         cin>>buf;
    136         cout<<AC.Query(buf)<<endl;
    137     }
    138     return 0;
    139 }
    View Code
  • 相关阅读:
    360抢票王验证码自动识别真的那么牛吗?
    wpf 的各个template
    HTML/CSS实现的一个列表页
    泛型约束和利用反射修改对象属性的值
    KindEditor富文本编辑器, 从客户端中检测到有潜在危险的 Request.Form 值
    检查对象是否为NULL或者为Empty
    【笔记】WPF实现ViewPager引导界面效果及问题汇总
    【笔记】WPF之模板控件应用
    【笔记】W3C CSS关键属性
    【转】Web标准中的常见问题
  • 原文地址:https://www.cnblogs.com/wsy107316/p/11455270.html
Copyright © 2011-2022 走看看