• 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 }
    静态数组
  • 相关阅读:
    HDC,CDC,CWindowDC,CClientDC,CPaintDC基础 笑风生 博客频道 CSDN.NET
    用web用户控件的方式添加到webpart,使用ajax实现无刷新总结
    .net 中利用owc 画制图表
    未安装在此服务器场中,无法添加到该范围
    敏捷软件开发宣言及原则
    调试 Windows SharePoint Services Workflow
    系统提示"System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本"解决办法
    安装及删除网站模板
    无法安装功能“265e193c6477431e8d3c98f51e6d3247”,因为加载事件接收器程序集“Microsoft.Office.Workflow.Feature, Version=12.0.0.0, Culture=neutral, PublicKeyToken=a5e1d8429183b844”
    表单加载出错
  • 原文地址:https://www.cnblogs.com/wangrunhu/p/9544900.html
Copyright © 2020-2023  润新知