• AC自动机-hdu2222 hdu2896


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

    题目大意:给定一堆模式串和一个匹配串,问匹配串中包含多少模式串

    AC自动机板子中的板子题。AC自动机的前需知识是KMP和trie树(字典树),需要的KMP的思想就是失配之后的最优化处理。事实上,AC自动机是在trie树上做一个失配最优化,也就是在trie树的基础上建立fail树。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<queue>
     5 using namespace std;
     6 
     7 #define maxn 1000005
     8 
     9 int trie[maxn][26];
    10 int fail[maxn];
    11 int cntword[maxn];
    12 int cnt;
    13 
    14 void insertWords(char s[])
    15 {
    16     int root=0;
    17     int len=strlen(s);
    18     for(int i=0;i<len;i++)
    19     {
    20         int next=s[i]-'a';
    21         if(!trie[root][next]){
    22             trie[root][next]=++cnt;
    23         }
    24         root=trie[root][next];
    25     }
    26     cntword[root]++;
    27 }
    28 
    29 void getFail()
    30 {
    31     queue<int>q;
    32     while(!q.empty()) q.pop();
    33     int now=0;
    34     for(int i=0;i<26;i++){
    35         if(trie[now][i]){
    36             fail[trie[now][i]]=0;
    37             q.push(trie[now][i]);
    38         }
    39     }
    40     while(!q.empty()){
    41         now = q.front();
    42         q.pop();
    43         for(int i=0;i<26;i++){
    44             if(trie[now][i]){
    45                 fail[trie[now][i]]=trie[fail[now]][i];
    46                 q.push(trie[now][i]);
    47             }
    48             else trie[now][i]=trie[fail[now]][i];
    49         }
    50     }
    51 }
    52 
    53 int query(char s[])
    54 {
    55     int ans=0,now=0,len=strlen(s);
    56     for(int i=0;i<len;i++){
    57         now=trie[now][s[i]-'a'];
    58         for(int j=now;j&&cntword[j]!=-1;j=fail[j])
    59         {
    60             ans+=cntword[j];
    61             cntword[j]=-1;
    62         }
    63     }
    64     return ans;
    65 }
    66 
    67 int main()
    68 {
    69     int n;
    70     int t;
    71     scanf("%d",&t);
    72     char s[maxn];
    73     while(t--)
    74     {
    75         memset(fail,0,sizeof(fail));
    76         memset(trie,0,sizeof(trie));
    77         memset(cntword,0,sizeof(cntword));
    78         cnt=0;
    79         scanf("%d",&n);
    80         while(n--)
    81         {
    82             scanf("%s",s);
    83             insertWords(s);
    84         }
    85         fail[0]=0;
    86         getFail();
    87         scanf("%s",s);
    88         printf("%d
    ",query(s));
    89     }
    90     return 0;
    91 }
    hdu2222

    hdu2896 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896

    题目大意:给定n个模式串,m个匹配串,求每个匹配串中有哪写模式串,所有匹配串中有多少匹配到模式串。

    这题也是一道AC自动机板子题,比上面hdu2222稍有些难度,这里我们先将模式串构建好树,然后去跑匹配串,要注意的是这里不在是仅有小写字母,题目中说到:以上字符串中的字符都是ASCII码可见字符(不包括回车)。由于我们需要记录每个匹配串匹配结果信息,我们可以开一个存储空间存储这些信息。

      1 #include<stdio.h>
      2 #include<algorithm>
      3 #include<string.h>
      4 #include<queue>
      5 using namespace std;
      6 
      7 #define maxn 100005
      8 
      9 char a[505][205];
     10 int trie[maxn][130];
     11 int fail[maxn];
     12 int idword[maxn];
     13 int cnt=0;
     14 
     15 void insertWords(int id)
     16 {
     17     int len=strlen(a[id]);
     18     int now=0;
     19     for(int i=0;i<len;i++)
     20     {
     21         int next=a[id][i];
     22         if(!trie[now][next])
     23             trie[now][next]=++cnt;
     24         now=trie[now][next];
     25     }
     26     idword[now]=id;
     27 }
     28 
     29 void getFail()
     30 {
     31     queue<int> q;
     32     while(!q.empty()) q.pop();
     33     for(int i=0;i<130;i++)
     34     {
     35         if(trie[0][i]){
     36             fail[trie[0][i]]=0;
     37             q.push(trie[0][i]);
     38         }
     39     }
     40     int now=0;
     41     while(!q.empty()){
     42         int now=q.front();
     43         q.pop();
     44         for(int i=0;i<130;i++){
     45             if(trie[now][i]){
     46                 fail[trie[now][i]]=trie[fail[now]][i];
     47                 q.push(trie[now][i]);
     48             }
     49             else trie[now][i]=trie[fail[now]][i];
     50         }
     51     }
     52 }
     53 int an[505];
     54 int anss=0;
     55 void getans(char s[])
     56 {
     57     int len=strlen(s);
     58     int now=0;
     59     for(int i=0;i<len;i++){
     60         now=trie[now][s[i]];
     61         for(int j=now;j&&idword[j]!=0;j=fail[j]){
     62             if(!an[idword[j]])
     63             {
     64                 an[idword[j]]=1;
     65             anss++;
     66             }
     67         }
     68     }
     69 }
     70 
     71 int main()
     72 {
     73     int n,m;
     74     scanf("%d",&n);
     75     for(int i=1;i<=n;i++)
     76     {
     77         scanf("%s",a[i]);
     78         insertWords(i);
     79     }
     80     getFail();
     81     fail[0]=0;
     82     scanf("%d",&m);
     83     char s[10005];
     84     int ans=0;
     85     for(int i=1;i<=m;i++)
     86     {
     87         anss=0;
     88         memset(an,0,sizeof(an));
     89         scanf("%s",s);
     90         getans(s);
     91         if(anss!=0){
     92             //printf("anss=%d
    ",anss);
     93             ans++;
     94             printf("web %d: ",i);
     95             for(int j=1;j<=n;j++)
     96             {
     97                 if(an[j]){
     98                     anss--;
     99                     if(anss)
    100                         printf("%d ",j);
    101                     else {
    102                         printf("%d
    ",j);break;
    103                     }
    104                 }
    105             }
    106         }
    107     }
    108     printf("total: %d
    ",ans);
    109     return 0;
    110 }
    hdu2896
  • 相关阅读:
    观察者模式
    工厂模式
    单例模式
    代理模式
    策略模式
    Ioc容器
    Spring概述
    02:入门
    01:背景
    编译原理感悟
  • 原文地址:https://www.cnblogs.com/noback-go/p/13306947.html
Copyright © 2020-2023  润新知