zoukankan      html  css  js  c++  java
  • [hdu2222]Keywords Search(AC自动机)

    题意:给定n个单词,一个字符串,问字符串中出现了多少个单词。

    解题关键:AC自动机模板题,注意根据题意,匹配完成之后要置0.

    注意char数组也可以用cin,

    注意理解AC自动机,不可能在同一层 出现两个相同的前缀,不然会合并在一起的,所以一定会分层,所以可以依靠fail指针递归寻找。

    AC自动机最重要的地方在于 用后缀来匹配前缀

    复杂度:$O(NS + T)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=26;
     5 const int MAXN=520000;
     6 struct Trie{//数组形式 
     7     int Next[MAXN][N],Fail[MAXN],End[MAXN],root,tot;//大小为所以匹配字符串的总和 
     8     int newnode(){//结构体内部用 
     9         for(int i=0;i<N;i++) Next[tot][i]=-1;
    10         End[tot++]=0;
    11         return tot-1;
    12     }
    13     void init(){
    14         tot=0;
    15         root=newnode();
    16     }
    17     void insert(char buf[]){
    18         int len=strlen(buf);
    19         int now=root;//now是temp指针 
    20         for(int i=0;i<len;i++){
    21             int k=buf[i]-'a';
    22             if(Next[now][k]==-1)  Next[now][k]=newnode();//next数组代表的是下一个字符索引 
    23             now=Next[now][k];
    24         }
    25         End[now]++;//end数组是当前字符串的个数.字典中可能有相同的单词,若只算一次,改为1. 
    26     }
    27     void build(){//构造fail指针,后缀是某些前缀 
    28         queue<int>que;
    29         Fail[root]=root;
    30         for(int i=0;i<N;i++){ 
    31             if(Next[root][i]==-1) Next[root][i]=root;
    32             else{
    33                 Fail[Next[root][i]]=root;
    34                 que.push(Next[root][i]);
    35             }
    36         } 
    37         while(!que.empty()){//bfs,会将所有的匹配子串都遍历到 
    38             int now=que.front();
    39             que.pop();
    40             for(int i=0;i<N;i++){
    41                 if(Next[now][i]==-1) Next[now][i]=Next[Fail[now]][i];
    42                 else{
    43                     Fail[Next[now][i]]=Next[Fail[now]][i];
    44                     que.push(Next[now][i]);
    45                 }
    46             }
    47         }
    48     }
    49     int query(char buf[]){
    50         int len=strlen(buf),now=root,res=0;
    51         for(int i=0;i<len;i++){
    52             now=Next[now][buf[i]-'a'];
    53             int temp=now;
    54             while(temp!=root){
    55                 res+=End[temp];
    56                 End[temp]=0;//模式串只在主串中匹配一次就可以了,若匹配次数算作n次,次数不必置0 
    57                 temp=Fail[temp];
    58             }
    59         }
    60         return res;
    61     }
    62 };
    63 Trie ac;
    64 char buf[1000003];
    65 int main(){
    66     int T,n;
    67     ios::sync_with_stdio(0); 
    68     cin>>T;
    69     while(T--){
    70         ac.init();
    71         cin>>n;
    72         for(int i=0;i<n;i++){
    73             cin>>buf;
    74             ac.insert(buf);
    75         }
    76         ac.build();//不要忘记build 
    77         cin>>buf;
    78         int ans=ac.query(buf);
    79         cout<<ans<<"
    ";
    80     }
    81     return 0;
    82 } 
  • 相关阅读:
    iOS- 移动端Socket UDP协议广播机制的实现
    iOS- 三步快速集成社交化分享工具ShareSDK
    iOS- iOS 7 的后台多任务 (Multitasking) 对比之前的异同、具体机制、变化
    iOS- Exception异常处理
    17. Subsets【medium】
    zookeeper程序员指南
    error while loading shared libraries错误解决
    82. Single Number【easy】
    53. Reverse Words in a String【easy】
    查看linux内核和版本信息
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7503090.html
Copyright © 2011-2022 走看看