Dominating Patterns(Aho_corasick入门)

算是ac自动机的入门题了吧。就是给了最多170个长为最多70的模板串,然后给出一个文本串,让按输入顺序输出所有的文本串匹配点最多的那些串。

因为模板串多个且长度较小,而文本串较长1e6,所

#include <queue>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define rep(i,n) for(int (i)=0;(i)<(n);i++)
#define Rep(i,n) for(int (i)=1;(i)<=(n);i++)
#define rep1(i,x,y) for(int (i)=x;(i)<=y;i++)

const int sigmasize = 26;
const int N = 71*151;
struct Aho_Corasick{
 int ch[N][sigmasize];
 int val[N],last[N],f[N],cou[N];
 int cnt;
 map<string,int> ms;
 int idx(char c){return c-'a';}
 void clear(){
    cnt = 1;
    memset(val,0,sizeof(val));
    memset(ch[0],0,sizeof(ch[0]));
    memset(cou,0,sizeof(cou));
    ms.clear();
 }
 void insert(char* s,int v){
   int n=strlen(s),u=0;
   rep(i,n){
     int c=idx(s[i]);
     if(!ch[u][c]){
        ch[u][c] = cnt;
        memset(ch[cnt],0,sizeof(ch[cnt]));
        cnt++;
        }
        u = ch[u][c];
        }
         val[u] = v;
         ms[string(s)]=v;
 }
 void print(int i,int u){
    if(u){
      // printf("%d is found st position %d\n",val[u],i);
       cou[val[u]]++;
       print(i,last[u]);
    }
 }
 void find(char* T){
     int n=strlen(T),j=0;
     rep(i,n){
        int c=idx(T[i]);
        j = ch[j][c];
        if(val[j]) print(i,j);
        else if(last[j]) print(i,last[j]);
     }
 }
 void init(){
    queue<int> Q;
    last[0]=f[0]=0;
    rep(i,sigmasize){
        if(ch[0][i]) {
            f[ch[0][i]]=last[i]=0;
            Q.push(ch[0][i]);
        }
    }
    while(!Q.empty()){
        int r=Q.front(); Q.pop();
        rep(i,sigmasize){
            int u=ch[r][i];
            if(!u){ch[r][i]=ch[f[r]][i]; continue;}
            f[u]=ch[f[r]][i];
            last[u] = val[f[u]] ? f[u]:last[f[u]];
            Q.push(u);
        }
    }
 }
};
int n,Q;
char str[180][100],src[1010101];
int main()
{
    Aho_Corasick ac;
    while(scanf("%d",&n)==1 && n){
        ac.clear();
        Rep(i,n){

           scanf("%s",str[i]);
           ac.insert(str[i],i);
        }
        ac.init();
        scanf("%s",src);
        ac.find(src);
        int best = 0;
        Rep(i,n) if(ac.cou[i]>best) {
        best=ac.cou[i];
        }

        printf("%d\n",best);
        Rep(i,n){
          if(ac.cou[ac.ms[string(str[i])]] == best)
               printf("%s\n",str[i]);
        }
    }
    return 0;
}

以用ac自动机正合适,注意输出时重复的模板会覆盖前面的模板,要加一个ma<string,int>标记每个模板串最后出现的位置

即可。


你可能感兴趣的:(Algorithm,C++,算法,uva)