Dominating Patterns UVALive - 4670 (ac自动机)

Dominating Patterns

 UVALive - 4670 

题意:给n个短串1个长串,问这个长串中出现次数最多的短串,并输出

学习了lrj不用指针的写法

需要注意的是模板串可能有重复,用map搞一下

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define CLR(m,a) memset(m,a,sizeof(m))
  4 #define LL long long
  5 const int maxnode=11000;
  6 const int sigma=26;
  7 const int maxn=160;
  8 map<string,int> mp;
  9 struct AC
 10 {
 11     int ch[maxnode][sigma];
 12     int f[maxnode],val[maxnode],last[maxnode];
 13     int sz;
 14     int cnt[maxn];  //
 15 
 16     void init()
 17     {
 18         CLR(ch[0],0);
 19         CLR(cnt,0);
 20         sz=1;
 21     }
 22     int idx(char c) {return c-'a';}
 23     void inser(char *s,int v)
 24     {
 25         int u=0,n=strlen(s);
 26         for(int i=0;i<n;i++){
 27             int c=idx(s[i]);
 28             if(!ch[u][c]){
 29                 CLR(ch[sz],0);
 30                 val[sz]=0;
 31                 ch[u][c]=sz++;
 32             }
 33             u=ch[u][c];
 34         }
 35         val[u]=v;
 36     }
 37     void print(int u)
 38     {
 39         if(u){
 40             cnt[val[u]]++;
 41             print(last[u]);
 42         }
 43     }
 44     void fin(char *s)
 45     {
 46         int n=strlen(s);
 47         int u=0;
 48         for(int i=0;i<n;i++){
 49             int c=idx(s[i]);
 50             while(u&&!ch[u][c]) u=f[u];
 51             u=ch[u][c];
 52             if(val[u]) print(u);
 53             else if(last[u]) print(last[u]);
 54         }
 55     }
 56     void getfail()
 57     {
 58         queue<int> q;
 59         f[0]=0;
 60         for(int c=0;c<sigma;c++){
 61             int u=ch[0][c];
 62             if(u){
 63                 f[u]=0;
 64                 q.push(u);
 65                 last[u]=0;
 66             }
 67         }
 68         while(!q.empty()){
 69             int r=q.front();
 70             q.pop();
 71             for(int c=0;c<sigma;c++){
 72                 int u=ch[r][c];
 73                 if(!u) continue;
 74                 q.push(u);
 75                 int v=f[r];
 76                 while(v&&!ch[v][c]) v=f[v];
 77                 f[u]=ch[v][c];
 78                 last[u]=val[f[u]]?f[u]:last[f[u]];
 79             }
 80         }
 81     }
 82 };
 83 AC ac;
 84 char s[1000010],p[155][80];
 85 int n;
 86 int main()
 87 {
 88     while(scanf("%d",&n)&&n){
 89         ac.init();
 90         mp.clear();
 91         for(int i=1;i<=n;i++){
 92             scanf("%s",p[i]);
 93             mp[p[i]]=i;
 94             ac.inser(p[i],i);
 95         }
 96         ac.getfail();
 97         scanf("%s",s);
 98         ac.fin(s);
 99         int ans=-1;
100         for(int i=1;i<=n;i++) if(ac.cnt[i]>ans) ans=ac.cnt[i];
101         printf("%d\n",ans);
102         for(int i=1;i<=n;i++) if(ans==ac.cnt[mp[p[i]]])
103             printf("%s\n",p[i]);
104     }
105     return 0;
106 }
View Code

 

转载于:https://www.cnblogs.com/yijiull/p/7388271.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值