zoukankan      html  css  js  c++  java
  • HDU 2222 Keywords Search(ac自动机模板)

    Keywords Search

    Problem Description
    In the modern time, Search engine came into the life of everybody like Google, Baidu, etc.
    Wiskey also wants to bring this feature to his image retrieval system.
    Every image have a long description, when users type some keywords to find the image, the system will match the keywords with description of image and show the image which the most keywords be matched.
    To simplify the problem, giving you a description of image, and some keywords, you should tell me how many keywords will be match.
     
    Input
    First line will contain one integer means how many cases will follow by.
    Each case will contain two integers N means the number of keywords and N keywords follow. (N <= 10000)
    Each keyword will only contains characters 'a'-'z', and the length will be not longer than 50.
    The last line is the description, and the length will be not longer than 1000000.
     
    Output
    Print how many keywords are contained in the description.
     
    Sample Input
    1
    5
    she
    he
    say
    shr
    her
    yasherhs
     
    Sample Output
    3

     以前总以为字符串很难学就一直没认真去学,遇见字符串的题,大部分都果断放弃了,哇现在看来真的是后悔。只要认真,学的还是挺快的

    思路:ac自动机的模板题啦,找了很多大神的博客讲解ac自动机,终于算是弄懂一点点了吧,还是直接附上代码吧,都是套模板的题

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<string>
     6 #include<queue>
     7 using namespace std;
     8 struct node {
     9     int data;
    10     node *fail;
    11     node *next[26];
    12     node() {
    13         data = 0; fail = NULL;
    14         memset(next, 0, sizeof(next));
    15     }
    16 };
    17 node* Insert(node *root, string str)
    18 {
    19     node *p = root;
    20     int len = str.length();
    21     for (int i = 0; str[i]; i++) {
    22         int x = str[i] - 'a';
    23         if (p->next[x] == NULL)
    24             p->next[x] = new node;
    25         p = p->next[x];
    26     }
    27     p->data++;
    28     return root;
    29 }
    30 void build_ac(node *root)
    31 {
    32     node *p, *tmp;
    33     queue<node*>Q;
    34     Q.push(root);
    35     while (!Q.empty()){
    36         p = Q.front(); Q.pop();
    37         for (int i = 0; i < 26; i++) {
    38             if (p->next[i] != NULL) {
    39                 if (p == root)
    40                     p->next[i]->fail = root;
    41                 else {
    42                     tmp = p->fail;
    43                     while (tmp) {
    44                         if (tmp->next[i]) {
    45                             p->next[i]->fail = tmp->next[i];
    46                             break;
    47                         }
    48                         tmp = tmp->fail;
    49                     }
    50                     if (tmp == NULL)p->next[i]->fail = root;
    51                 }
    52                 Q.push(p->next[i]);
    53             }
    54         }
    55     }
    56 }
    57 int ac(node *root, string str)
    58 {
    59     int ans = 0, len = str.length();
    60     node *p = root, *tmp;
    61     for (int i = 0; i < len; i++) {
    62         while (p->next[str[i] - 'a'] == NULL && p != root)p = p->fail;
    63         p = p->next[str[i] - 'a'];
    64         if (p == NULL)p = root;
    65         tmp = p;
    66         while (tmp != root && tmp->data != -1) {
    67             ans += tmp->data;
    68             tmp->data = -1;
    69             tmp = tmp->fail;
    70         }
    71     }
    72     return ans;
    73 }
    74 int main()
    75 {
    76     ios::sync_with_stdio(false);
    77     int t, n;
    78     cin >> t;
    79     while (t--) {
    80         cin >> n;
    81         string s; node *root = new node;
    82         for (int i = 0; i < n; i++) {
    83             cin >> s;
    84             Insert(root, s);
    85         }
    86         build_ac(root);
    87         cin >> s;
    88         cout << ac(root, s) << endl;
    89     }
    90     return 0;
    91 }
    链表

    有时候对空间要求比较高的时候用链表会爆空间,可能就需要使用静态数组来代替指针,也可以根据题目要求来限制插入字典树的单词个数来降低空间复杂度例如 HDU 1671

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<string>
     5 #include<queue>
     6 
     7 using namespace std;
     8 const int maxn = 1000010;
     9 const int max_tot = 500010;
    10 const int max_size = 26;
    11 char s[maxn], t[100];
    12 struct AC {
    13     int trie[max_tot][max_size];
    14     int val[max_tot];
    15     int fail[max_tot], last[max_tot];
    16     int size;
    17     void Clear()
    18     {
    19         memset(trie[0], 0, sizeof(trie[0]));
    20         size = 1;
    21     }
    22     int idx(char x) { return x - 'a'; }
    23     void insert(char *str) {
    24         int k = 0;
    25         for (int i = 0; str[i]; i++) {
    26             int x = idx(str[i]);
    27             if (!trie[k][x]) {
    28                 memset(trie[size], 0, sizeof(trie[size]));
    29                 val[size] = 0;
    30                 trie[k][x] = size++;
    31             }
    32             k = trie[k][x];
    33         }
    34         val[k]++;
    35     }
    36     void GetFail()
    37     {
    38         queue<int>Q;
    39         fail[0] = 0; int k = 0;
    40         for (int i = 0; i < max_size; i++) {//计算第一层的fail指针跟last指针
    41             k = trie[0][i];
    42             if (k) {
    43                 Q.push(k);
    44                 fail[k] = 0;
    45                 last[k] = 0;
    46             }
    47         }
    48         while (!Q.empty()) {
    49             int r = Q.front(); Q.pop();
    50             for (int i = 0; i < max_size; i++) {
    51                 k = trie[r][i];
    52                 if (!k) {
    53                     trie[r][i] = trie[fail[r]][i];
    54                     continue;
    55                 }
    56                 Q.push(k);
    57                 int v = fail[r];
    58                 while (v && !trie[v][i])v = fail[k];
    59                 fail[k] = trie[v][i];
    60                 last[k] = (val[fail[k]] ? fail[k] : last[fail[k]]);
    61             }
    62         }
    63     }
    64     int Find(char *str) {
    65         int k = 0, cnt = 0;
    66         for (int i = 0; str[i]; i++) {
    67             int x = idx(str[i]);
    68             k = trie[k][x];
    69             int tmp = 0;
    70             if (val[k])tmp = k;
    71             else if (last[k])tmp = last[k];
    72             while (tmp) {
    73                 cnt += val[tmp];
    74                 val[tmp] = 0;
    75                 tmp = last[tmp];
    76             }
    77         }
    78         return cnt;
    79     }
    80 }ac;
    81 int main()
    82 {
    83     ios::sync_with_stdio(false);
    84     int t, n;
    85     cin >> t;
    86     while (t--) {
    87         cin >> n;
    88         ac.Clear();
    89         for (int i = 1; i <= n; i++) {
    90             cin >> s;
    91             ac.insert(s);
    92         }
    93         ac.GetFail();
    94         cin >> s;
    95         cout << ac.Find(s) << endl;
    96     }
    97     return 0;
    98 }
    静态数组
  • 相关阅读:
    值得收藏的十二条Jquery随身笔记
    都来中大奖啦~双色球随机算法!
    巧妙使用div+css模拟表格对角线
    介绍两个非常好用的Javascript内存泄漏检测工具
    JQuery模仿淘宝天猫魔盒抢购页面倒计时效果
    JQuery巧妙利用CSS操作打印样式
    boost编译随笔
    Dev-C++安装第三方库boost
    比特币源码分析--C++11和boost库的应用
    QT +go 开发 GUI程序
  • 原文地址:https://www.cnblogs.com/wangrunhu/p/9544900.html
Copyright © 2011-2022 走看看