zoukankan      html  css  js  c++  java
  • (AC自动机)UVALive

    题目地址

    每组数据,对模式串建立Trie树,为避免模式串重复的情况,用mao建立模式串与编号的对应关系。

    对匹配串AC自动机处理,其中print改为更新出现次数。

    最后找一下次数最大的输出即可。

      1 #include <iostream>
      2 #include <string>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <queue>
      8 #include <set>
      9 #include <map>
     10 #include <list>
     11 #include <vector>
     12 #include <stack>
     13 #define mp make_pair
     14 #define MIN(a,b) (a>b?b:a)
     15 #define rank rankk
     16 //#define MAX(a,b) (a>b?a:b)
     17 typedef long long ll;
     18 typedef unsigned long long ull;
     19 const int MAX=1e6+5;
     20 const int INF=1e9+5;
     21 const int B=1024;//桶的大小
     22 const double M=4e18;
     23 using namespace std;
     24 const int MOD=1e9+7;
     25 typedef pair<int,int> pii;
     26 const double eps=0.000000001;
     27 
     28 map<string,int> re;
     29 const int SIGMA_SIZE=50;
     30 const int MAXNODE=11000;
     31 const int MAXS=160;
     32 /*
     33     由于失配过程比较复杂,要反复沿着失配边走,
     34     在实践中常常会把下述自动机改造一下,把所有不存在的边“补上”
     35     即把计算失配函数中的语句if(!u)continue;改成
     36     if(!u){ch[r][c]=ch[f[r]][c];continue;}
     37     这样,就完全不需要失配函数,而是对所有转移一视同仁
     38     即find函数中的while(j&&!ch[j][c])j=f[j] 可以直接删除
     39 
     40 */
     41 struct AhoCorasickAutomata
     42 {
     43     int ch[MAXNODE][SIGMA_SIZE];
     44     int f[MAXNODE];//fail函数
     45     int val[MAXNODE];//每个字符串的结尾结点都有非0的val
     46     int last[MAXNODE];//输出链表的下一个单词结点
     47     int num;//trie树编号(亦为包含根结点的当前size)
     48     int cnt[MAXNODE];
     49     //初始化
     50     void init()
     51     {
     52         num=1;
     53         memset(ch[0],0,sizeof(ch[0]));
     54         re.clear();
     55         memset(cnt,0,sizeof(cnt));
     56     }
     57     //返回字符对应编号
     58     int idx(char c)
     59     {
     60         return c-'a';
     61     }
     62     //插入权值为v的字符串
     63     void insert(char *s,int v)
     64     {
     65         int u=0,n=strlen(s);
     66         for(int i=0;i<n;i++)
     67         {
     68             int c=idx(s[i]);
     69             if(!ch[u][c])
     70             {
     71                 memset(ch[num],0,sizeof(ch[num]));
     72                 val[num]=0;
     73                 ch[u][c]=num++;
     74             }
     75             u=ch[u][c];
     76         }
     77         val[u]=v;
     78         re[s]=v;
     79     }
     80     //递归打印以结点j结尾的所有字符串
     81     void print(int j)
     82     {
     83         if(j)
     84         {
     85             ++cnt[val[j]];
     86             print(last[j]);
     87 //            printf("%d %d
    ",j,val[j]);
     88 //            print(last[j]);
     89         }
     90     }
     91     //计算fail函数
     92     void getFail()
     93     {
     94         queue <int> que;
     95         f[0]=0;
     96         for(int c=0;c<SIGMA_SIZE;c++)
     97         {
     98             int u=ch[0][c];
     99             if(u)
    100             {
    101                 f[u]=0;que.push(u);last[u]=0;
    102             }
    103         }
    104         while(!que.empty())
    105         {
    106             int r=que.front();que.pop();
    107             for(int c=0;c<SIGMA_SIZE;c++)
    108             {
    109                 int u=ch[r][c];
    110                 if(!u)
    111                     continue;
    112                 que.push(u);
    113                 int v=f[r];
    114                 while(v&&!ch[v][c])//类似kmp的过程
    115                     v=f[v];
    116                 f[u]=ch[v][c];
    117                 last[u]=val[f[u]]?f[u]:last[f[u]];
    118             }
    119         }
    120     }
    121     //在T中中模板
    122     int find(char *T)
    123     {
    124         int n=strlen(T);
    125         int u=0;//当前结点编号,初始为根结点
    126         for(int i=0;i<n;i++)//文本串当前指针
    127         {
    128             int c=idx(T[i]);
    129             while(u&&!ch[u][c])//顺着失配指针走,直到可以匹配或回到根节点
    130                 u=f[u];
    131             u=ch[u][c];
    132             if(val[u])//当前位置恰好是某个模式串第一次出现
    133                 print(u);
    134             else if(last[u])//当前位置作为后缀,与某前缀与模式串相同
    135                 print(last[u]);
    136         }
    137     }
    138 
    139 };
    140 int n;
    141 char tem[151][80];
    142 char temp[MAX];
    143 AhoCorasickAutomata ac;
    144 int main()
    145 {
    146     while(scanf("%d",&n)&&n)
    147     {
    148         ac.init();
    149         for(int i=1;i<=n;i++)
    150         {
    151             scanf("%s",tem[i]);
    152             ac.insert(tem[i],i);
    153         }
    154         ac.getFail();
    155         scanf("%s",temp);
    156         ac.find(temp);
    157         int an=-1;
    158         for(int i=1;i<=n;i++)
    159         {
    160             if(ac.cnt[i]>an)
    161             {
    162                 an=ac.cnt[i];
    163             }
    164         }
    165         printf("%d
    ",an);
    166         for(int i=1;i<=n;i++)
    167         {
    168             if(ac.cnt[re[string(tem[i])]]==an)
    169                {
    170                    printf("%s
    ",tem[i]);
    171                }
    172         }
    173     }
    174     return 0;
    175 }
  • 相关阅读:
    MySQL-3(练习题)-三套知识点看完SQL没问题
    MySQL知识点-2(超详细)
    MySQL知识点-1(超详细)
    MySQL表结构笔记9
    MySQL增删改查&数据类型笔记8
    07:表联结MySQL笔记7
    spring事务传播机制
    MySQL查看两个查询的差集
    python连接数据库
    chrome一款可以在浏览器编辑hosts文件的插件HostAdmin App
  • 原文地址:https://www.cnblogs.com/quintessence/p/6898669.html
Copyright © 2011-2022 走看看