• HDU 2222 Keywords Search(AC自动机)


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

    题意:给你n个模式串,一个长为m的主串,问有多少个模式串在主串中出现了(模式串可能重复)

    思路:AC自动机水题,先根据这n个模式串建立trie树,再构造fail指针,最后扫描主串即可。

    code:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 using namespace std;
      5 const int KIND = 26;
      6 
      7 struct node
      8 {
      9     int num;
     10     node* fail;
     11     node* next[KIND];
     12     node()
     13     {
     14         num = 0;
     15         fail = NULL;
     16         for (int i = 0; i < KIND; ++i) next[i] = NULL;
     17     }
     18 };
     19 node* root;
     20 
     21 void Insert(char str[])
     22 {
     23     node* temp = root;
     24     int len = strlen(str);
     25     for (int i = 0; i < len; ++i)
     26     {
     27         int curr = str[i] - 'a';
     28         if (temp->next[curr] == NULL)
     29             temp->next[curr] = new node();
     30         temp = temp->next[curr];
     31     }
     32     ++(temp->num);
     33 }
     34 
     35 void Build()
     36 {
     37     queue<node*> Q;
     38     root->fail = root;
     39     for (int i = 0; i < KIND; ++i)
     40     {
     41         if (root->next[i] == NULL)
     42             root->next[i] = root;
     43         else
     44         {
     45             root->next[i]->fail = root;
     46             Q.push(root->next[i]);
     47         }
     48     }
     49     while (!Q.empty())
     50     {
     51         node* temp = Q.front();
     52         Q.pop();
     53         for (int i = 0; i < KIND; ++i)
     54         {
     55             if (temp->next[i] == NULL)
     56                 temp->next[i] = temp->fail->next[i];
     57             else
     58             {
     59                 temp->next[i]->fail = temp->fail->next[i];
     60                 Q.push(temp->next[i]);
     61             }
     62         }
     63     }
     64 }
     65 
     66 int Query(char str[])
     67 {
     68     int len = strlen(str);
     69     node* temp = root;
     70     int res = 0;
     71     for (int i = 0; i < len; ++i)
     72     {
     73         int curr = str[i] - 'a';
     74         temp = temp->next[curr];
     75         node* x = temp;
     76         while (x != root)
     77         {
     78             res += x->num;
     79             x->num = 0;
     80             x = x->fail;
     81         }
     82     }
     83     return res;
     84 }
     85 
     86 char str[1000010];
     87 int main()
     88 {
     89     int nCase;
     90     scanf("%d", &nCase);
     91     while (nCase--)
     92     {
     93         int n;
     94         scanf("%d", &n);
     95         root = new node();
     96         for (int i = 0; i < n; ++i)
     97         {
     98             scanf("%s", str);
     99             Insert(str);
    100         }
    101         Build();
    102         scanf("%s", str);
    103         printf("%d
    ", Query(str));
    104     }
    105     return 0;
    106 }

     数组实现:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 using namespace std;
      5 const int KIND = 26;
      6 const int MAXN = 500005;
      7 const int MAXM = 1000005;
      8 
      9 struct Trie
     10 {
     11     int next[MAXN][KIND], fail[MAXN], end[MAXN];
     12     int root, L;
     13 
     14     int create()
     15     {
     16         for (int i = 0; i < KIND; ++i)
     17             next[L][i] = -1;
     18         end[L++] = 0;
     19         return L - 1;
     20     }
     21 
     22     void init()
     23     {
     24         L = 0;
     25         root = create();
     26     }
     27 
     28     void insert(char str[])
     29     {
     30         int now = root;
     31         int len = strlen(str);
     32         for (int i = 0; i < len; ++i)
     33         {
     34             int curr = str[i] - 'a';
     35             if (next[now][curr] == -1)
     36                 next[now][curr] = create();
     37             now = next[now][curr];
     38         }
     39         ++end[now];
     40     }
     41 
     42     void build()
     43     {
     44         queue<int>Q;
     45         fail[root] = root;
     46         for (int i = 0; i < KIND; ++i)
     47         {
     48             if (next[root][i] == -1)
     49                 next[root][i] = root;
     50             else
     51             {
     52                 fail[next[root][i]] = root;
     53                 Q.push(next[root][i]);
     54             }
     55         }
     56         while (!Q.empty())
     57         {
     58             int now = Q.front();
     59             Q.pop();
     60             for (int i = 0; i < KIND; ++i)
     61             {
     62                 if (next[now][i] == -1)
     63                     next[now][i] = next[fail[now]][i];
     64                 else
     65                 {
     66                     fail[next[now][i]] = next[fail[now]][i];
     67                     Q.push(next[now][i]);
     68                 }
     69             }
     70         }
     71     }
     72 
     73     int query(char str[])
     74     {
     75         int now = root;
     76         int len = strlen(str);
     77         int res = 0;
     78         for (int i = 0; i < len; ++i)
     79         {
     80             int curr = str[i] - 'a';
     81             now = next[now][curr];
     82             int temp = now;
     83             while (temp != root)
     84             {
     85                 res += end[temp];
     86                 end[temp] = 0;
     87                 temp = fail[temp];
     88             }
     89         }
     90         return res;
     91     }
     92 };
     93 
     94 Trie ac;
     95 char str[MAXM];
     96 int main()
     97 {
     98     int nCase;
     99     scanf("%d", &nCase);
    100     while (nCase--)
    101     {
    102         int n;
    103         scanf("%d", &n);
    104         ac.init();
    105         for (int i = 0; i < n; ++i)
    106         {
    107             scanf("%s", str);
    108             ac.insert(str);
    109         }
    110         ac.build();
    111         scanf("%s", str);
    112         printf("%d
    ", ac.query(str));
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    记录C#开发遇到的问题和应用经验
    HttpApplication,HttpModule,HttpContext及Asp.Net页生命周期
    itextsharp.dll(4.0.8.0)完整示例PDF
    步步为营 .NET 设计模式学习笔记 二十三、Interpreter(解释器模式)
    .net简谈分层架构思想
    FusionCharts Free
    表解锁的方法
    步步为营 .NET 设计模式学习笔记 二十一、Visitor(访问者模式)
    步步为营 .NET 设计模式学习笔记 二十二、Memento(备望录模式)
    再论抽象
  • 原文地址:https://www.cnblogs.com/ykzou/p/4583512.html
Copyright © 2020-2023  润新知