• Keywords Search


    Keywords Search

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 25356    Accepted Submission(s): 8280

    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
    text:100万长度,关键字1万,多个测试案例,用Trie匹配必定超时。Trie也可以多模式匹配,不多比AC自动机耗时太多。
    Trie 超时代码:
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <string>
     7 #include <vector>
     8 #include <stack>
     9 #include <queue>
    10 #include <set>
    11 #include <map>
    12 #include <iomanip>
    13 #include <cstdlib>
    14 using namespace std;
    15 const int INF=0x5fffffff;
    16 const int MS=10005;
    17 const double EXP=1e-8;
    18 
    19 struct node
    20 {
    21     int have;//根据情况灵活变化
    22     node * next[26];
    23 }nodes[MS*50];   //注意这个大小  尽量大一点
    24 
    25 node *root;
    26 int cnt,ans;
    27 
    28 char text[MS*100];
    29 
    30 node * add_node(int c)
    31 {
    32     node *p=&nodes[c];
    33     for(int i=0;i<26;i++)
    34         p->next[i]=NULL;
    35     p->have=0;
    36     return p;
    37 }
    38 
    39 void insert(char *str)
    40 {
    41     node *p=root;
    42     int len=strlen(str);
    43     for(int i=0;i<len;i++)
    44     {
    45         int id=str[i]-'a';
    46         if(p->next[id]==NULL)
    47         {
    48             p->next[id]=add_node(cnt++);
    49         }
    50         p=p->next[id];
    51     }
    52     p->have++;
    53 }
    54 void search(char *str)
    55 {
    56     node *p=root;
    57     int len=strlen(str);
    58     for(int i=0;i<len;i++)
    59     {
    60         int id=str[i]-'a';
    61         p=p->next[id];
    62         if(p==NULL)
    63             return ;
    64         if(p->have)
    65         {
    66             ans+=p->have;
    67             p->have=0;
    68         }
    69     }
    70 }
    71 
    72 int main()
    73 {
    74     int n,i,T;
    75     scanf("%d",&T);
    76     while(T--)
    77     {
    78         cnt=0;
    79         ans=0;
    80         root=add_node(cnt++);
    81         scanf("%d",&n);
    82         for(i=0;i<n;i++)
    83         {
    84             scanf("%s",text);
    85             insert(text);
    86         }
    87         scanf("%s",text);
    88         int len=strlen(text);
    89         for(i=0;i<len;i++)
    90         {
    91             search(text+i);
    92         }
    93         printf("%d
    ",ans);
    94     }
    95     return 0;
    96 }

    这题是AC自动机最经典的入门题。学会了kmp,Trie,就可以学习ac自动机了。

    time : 280 ms

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <string>
      7 #include <vector>
      8 #include <stack>
      9 #include <queue>
     10 #include <set>
     11 #include <map>
     12 #include <iomanip>
     13 #include <cstdlib>
     14 using namespace std;
     15 const int INF=0x5fffffff;
     16 const int MS=10005;
     17 const double EXP=1e-8;
     18 //  AC自动机  KMP  TRIE
     19 struct node
     20 {
     21     bool isbad;
     22     node *pre;
     23     node * next[26];
     24     int n;
     25 }nodes[MS*50];   //注意这个大小  个数*每个的长度就不会访问非法内存
     26 
     27 node *root;
     28 int cnt,ans;
     29 
     30 char text[MS*100];
     31 
     32 node * add_node(int c)
     33 {
     34     node *p=&nodes[c];
     35     for(int i=0;i<26;i++)
     36         p->next[i]=NULL;
     37     p->isbad=false;
     38     p->pre=NULL;
     39     p->n=0;
     40     return p;
     41 }
     42 
     43 void insert(char *str)
     44 {
     45     node *p=root;
     46     int len=strlen(str);
     47     for(int i=0;i<len;i++)
     48     {
     49         int id=str[i]-'a';
     50         if(p->next[id]==NULL)
     51         {
     52             p->next[id]=add_node(cnt++);
     53         }
     54         p=p->next[id];
     55     }
     56     p->isbad=true;
     57     p->n++;          //终止节点
     58 }
     59 
     60 void build()
     61 {                                 // 在trie树上加前缀指针
     62     for(int i=0;i<26;i++)
     63         nodes->next[i]=root;
     64     nodes->pre=NULL;
     65     root->pre=nodes;
     66     deque<node *> dq;
     67     dq.push_back(root);
     68     while(!dq.empty())
     69     {
     70         node *proot=dq.front();
     71         dq.pop_front();
     72         for(int i=0;i<26;i++)
     73         {
     74             node *p=proot->next[i];
     75             if(p!=NULL)
     76             {
     77                 node *pre=proot->pre;
     78                 while(pre)
     79                 {
     80                     if(pre->next[i]!=NULL)   //NULL==0
     81                     {
     82                         p->pre=pre->next[i];
     83                         if(p->pre->isbad)
     84                             p->isbad=true;
     85                         break;
     86                     }
     87                     else
     88                         pre=pre->pre;
     89                 }
     90                 dq.push_back(p);
     91             }
     92         }
     93     }
     94 }
     95 
     96 void search(char *str)
     97 {                    //返回值为true,说明包含模式串
     98     node *p=root;
     99     int len=strlen(str);
    100     for(int i=0;i<len;i++)
    101     {
    102         int id=str[i]-'a';
    103         while(p!=root&&p->next[id]==NULL)
    104         {
    105             p=p->pre;
    106         }
    107         p=p->next[id];
    108         if(p==NULL)
    109         {
    110             p=root;
    111         }
    112         node *tp=p;
    113         while(tp!=root&&tp->n!=0)
    114         {
    115             ans+=tp->n;
    116             tp->n=0;
    117             tp=tp->pre;
    118         }
    119 
    120         /*
    121         while(1)   是否包含模式串
    122         {
    123            if(p->next[id])
    124            {
    125                p=p->next[id];
    126                if(p->isbad)
    127                     return true;
    128                break;
    129            }
    130            else
    131             p=p->pre;
    132         }
    133         */
    134     }
    135 
    136     //return false;
    137 }
    138 
    139 int main()
    140 {
    141     int n,T;
    142     scanf("%d",&T);
    143     while(T--)
    144     {
    145         cnt=0;
    146         ans=0;
    147         add_node(cnt++);
    148         root=add_node(cnt++);
    149         scanf("%d",&n);
    150         for(int i=0;i<n;i++)
    151         {
    152             scanf("%s",text);
    153             insert(text);
    154         }
    155         build();
    156         scanf("%s",text);
    157         search(text);
    158         printf("%d
    ",ans);
    159     }
    160     return 0;
    161 }
    162 /*
    163 节点p的前缀指针定义为:指向树中出现
    164 过的S的最长的后缀(不能等于S)。
    165 如果p节点匹配失败,该节点对应c,就沿着它的父节点的前缀指针走,直到某节点,其儿子节点
    166 对应的字母也为c,把p节点的前缀指针指向该儿子节点。如果走到了root都没有找到,就指向root
    167 */
     
     
  • 相关阅读:
    苏州是新的一线城市拦路虎?
    SAP MM ME57界面看到的供应源跟Source List主数据不一致?
    SAP QM 检验批里样品数量的确定
    SAP QM 检验批里某检验特性的取样数量跟检验计划设置不符?
    SAP QM 主检验特性主数据关键字段解释
    SAP S4HANA TR传输之操作
    SAP QA32试图做UD,系统报错-工厂 BTYC中的 QM 基选设置需要维护
    使用 boost.asio 简单实现 异步Socket 通信
    fedora 28/29 配置 C++ 环境
    gitlab 和 github 配置 SSH Keys
  • 原文地址:https://www.cnblogs.com/767355675hutaishi/p/4305845.html
Copyright © 2020-2023  润新知