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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222

    题意:求字典中所有模式串各出现了多少次。

    建立AC自动机,查询的时候首先跳过所有cur->next[index]为NULL的情况,再跳过cur是root的情况。因为root不存任何信息。

    过滤完上述情况,那么当前匹配串上的index位置必然在trie上出现过,那么就沿着当前点的fail一路找上去。因为trie某节点的fail指针要么指向root,要么指向与当前字符相同的节点。接着记下每个点的cnt值,不要忘记置零防止重复统计。

    时隔多年(什么多年啊喂)重拾AC自动机,终于彻彻底底弄明白了。感恩的心。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 inline int GetId(char c) {
      5     return c - 'a';
      6 }
      7 typedef class Node {
      8 public:
      9     Node *next[26];
     10     Node *fail;
     11     int cnt;
     12     Node() {
     13         memset(next, 0, sizeof(next));
     14         fail = NULL;
     15         cnt = 0;
     16     }
     17 }Node;
     18 class AC_Automation {
     19 public:
     20     Node *root;
     21     queue <Node*> q;
     22     AC_Automation() {
     23         root = new Node;
     24         while(!q.empty()) q.pop();
     25     }
     26     void insert(string s) {
     27         Node *cur = root;
     28         int len = s.length();
     29         for(int i = 0; i < len; i++) {
     30             int index = GetId(s[i]);
     31             if(cur->next[index] == NULL) {
     32                 cur->next[index] = new Node;
     33             }
     34             cur = cur->next[index];
     35         }
     36         cur->cnt++;
     37     }
     38     void BuildAC() {
     39         Node *cur,*tmp;
     40         q.push(root);
     41         while(!q.empty()) {
     42             cur = q.front();
     43             q.pop();
     44             for(int i = 0; i < 26; i++) {
     45                 if(cur->next[i]) {
     46                     if(cur == root) {
     47                         cur->next[i]->fail = root;
     48                     }
     49                     else {
     50                         tmp = cur->fail;
     51                         while(tmp != NULL) {
     52                             if(tmp->next[i]) {
     53                                 cur->next[i]->fail = tmp->next[i];
     54                                 break;
     55                             }
     56                             tmp = tmp->fail;
     57                         } 
     58                         if(tmp == NULL) {
     59                             cur->next[i]->fail = root;
     60                         }
     61                     }
     62                     q.push(cur->next[i]);
     63                 }
     64             }
     65         }
     66     }
     67     int query(string s) {
     68         Node *cur = root,*tmp;
     69         int len = s.length();
     70         int ret = 0;
     71         for(int i = 0; i < len; i++) {
     72             int index = GetId(s[i]);
     73             while(cur->next[index] == NULL && cur != root) {
     74                 cur = cur->fail;
     75             }
     76             cur = cur->next[index];
     77             if(cur == NULL) {
     78                 cur = root;
     79                 continue;
     80             }
     81             tmp = cur;
     82             while(tmp != root) {
     83                 ret += tmp->cnt;
     84                 tmp->cnt = 0;
     85                 tmp = tmp->fail;
     86             }
     87         }
     88         return ret;
     89     }
     90 };
     91 char pat[52], tar[2000005];
     92 int n;
     93 
     94 int main() {
     95     // freopen("in", "r", stdin);
     96     int T;
     97     scanf("%d", &T);
     98     while(T--) {
     99         scanf("%d", &n);
    100         AC_Automation ac;
    101         for(int i = 0; i < n; i++) {
    102             scanf("%s", pat);
    103             ac.insert(pat);
    104         }
    105         ac.BuildAC();
    106         scanf("%s", tar);
    107         cout << ac.query(tar) << endl;
    108     }
    109     return 0;
    110 }
  • 相关阅读:
    sql 用Group by分组后,取每组的前几条记录
    mac安装 配置 ant
    js日期时间比较函数
    hibernate下载包中配置文件路径
    dbvis MySQL server version for the right syntax to use near 'OPTION SQL_SELECT_LIMIT=DEFAULT' at line 1
    严重: Exception starting filter struts2解决方法!
    【Linux】进程优先级、进程nice值和%nice
    【Algorithm】二分查找
    【php】thinkphp以post方式查询时分页失效的解决方法
    【C语言】练习5-8
  • 原文地址:https://www.cnblogs.com/kirai/p/6701729.html
Copyright © 2011-2022 走看看