UVA

https://vjudge.net/problem/UVA-1449

题意

 给你n个单词,还有一个长文本s,现在要你输出在文本s中出现次数最多的单词

分析

 AC自动机应用之一:统计每个模板串在原字符串中出现的次数

AC自动机的精华:利用last函数,将模板串的所有子串连接起来,只要沿着边走就可以遍历所有模板串的所有子串

对于重复的模板串题目要求重复输出,因此需要对每一个字符串对应一个序号,这就是它们的输入顺序,这样相同的字符串可以有两个不同的序号。实际上不用map。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
//#define eps 0.0000000001
#define IOS ios::sync_with_stdio(0);cin.tie(0);
#define random(a, b) rand()*rand()%(b-a+1)+a
#define pi acos(-1)
//const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
const int maxn = 1e6 + 10;
const int maxm = 4e5 +10;
const int mod = 20071027;
const int sigma_size = 26;

struct AC{
    int ch[maxn][sigma_size];
    int val[maxn];
    int last[maxn];
    int f[maxn];
    int cnt[maxn];
    int sz;
   
    void init(){
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(cnt,0,sizeof(cnt));
      
    }
    int idx(char c){ return c-'a'; }
    void insert(char* s,int v){
        int u = 0,n=strlen(s);
        for(int i=0;i<n;i++){
            int c=idx(s[i]);
            if(!ch[u][c]){
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz]=0;
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]=v;
  
    }
    void getFail(){
        queue<int> q;
        f[0]=0;
        for(int c=0;c<sigma_size;c++){
            int u=ch[0][c];
            if(u){
                f[u]=0;
                q.push(u);
                last[u]=0;
            }
        }
        while(!q.empty()){
            int r = q.front();q.pop();
            for(int c=0;c<sigma_size;c++){
                int u = ch[r][c];
                if(!u) {
                    ch[r][c]=ch[f[r]][c];
                    continue;
                }
                q.push(u);
                int v = f[r];
                while(v&&!ch[v][c]) v=f[v];
                f[u]=ch[v][c];
                last[u]=val[f[u]]?f[u]:last[f[u]];
            }
        }
    }
    void find(char* T){
        int n = strlen(T);
        int j=0;
        for(int i=0;i<n;i++){
            int c = idx(T[i]);
            j=ch[j][c];
            if(val[j]) print(j);
            else if(last[j]) print(last[j]);
        }
    }
    void print(int j){
        if(j){
            cnt[val[j]]++;
            print(last[j]);
        }
    }
};
AC ac;
char s[maxn],p[155][88];
int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//    freopen("input.txt", "w", stdout);
#endif
    int n;
    while(scanf("%d",&n)==1&&n){
        ac.init();
        for(int i=1;i<=n;i++){
            scanf("%s",p[i]);
            ac.insert(p[i],i);
        }
        ac.getFail();
        scanf("%s",s);
        ac.find(s);
        int bst=-1;
        for(int i=1;i<=n;i++) bst=max(bst,ac.cnt[i]);
        printf("%d
",bst);
        for(int i=1;i<=n;i++){
            if(ac.cnt[i]==bst) puts(p[i]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/fht-litost/p/9630077.html