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 }
    静态数组
  • 相关阅读:
    linux环境下时区无法设置(UTC无法更改为CST)的问题解决
    SUSE12 网卡配置、SSH远程配置、解决CRT密钥交换失败,没有兼容的加密程序
    SUSE12 操作系统安装
    Unity技术支持团队性能优化经验分享
    基于unity3d游戏的android版本逆向初探
    Unity手游引擎安全解析及实践
    盛大游戏技术总监徐峥:Unity引擎使用的三种方式
    基于Unity 5的次世代卡通渲染技术 -- Unite 2017 米哈游总监贺甲分享实录
    欢乐互娱庞池海:《龙之谷》项目性能优化经验分享
    ue4 htcvivi简单配置
  • 原文地址:https://www.cnblogs.com/wangrunhu/p/9544900.html
Copyright © 2011-2022 走看看