//目录

LA 4670 AC自动机

题意:给一个字典,看这个字典中匹配最多次数的是哪个单词(可以有多个)。

 

分析:

  • AC自动机就是用来解决多模式匹配问题的工具。
  • 模板用的lrj的,相比HDU 2222,动态开辟字典树。用last数组统计字典。
  • 统计每一个单词匹配的次数cnt[],下标唯一对应val,最后遍历一遍cnt。
#include <bits/stdc++.h>

using namespace std;

const int SIGMA_SIZE = 26;
const int MAXNODE = 11000;
const int MAXS = 150 +10;

map<string,int> ms;

struct Aho {
    int ch[MAXNODE][SIGMA_SIZE];
    int f[MAXNODE];
    int last[MAXNODE];
    int cnt[MAXS];
    int val[MAXNODE];
    int sz;

    void init() {
        sz = 1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(cnt,0,sizeof(cnt));
        ms.clear();
    }

    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;
        ms[string(s)] = 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) 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]];    //last 方便统计
            }
        }

    }

    void find(char* T) {
        int n = strlen(T);
        int j = 0;

        for(int i=0; i < n; i++) {
            int c = idx(T[i]);
            while(j&&!ch[j][c]) j = f[j];
            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]);
        }
    }

    
}aho;

int n,T;

char text[1000005],P[151][80];

int main(int argc, char const *argv[])
{
    while(scanf("%d",&n),n) {
        aho.init();

        for(int i=1; i <= n; i++) {
            scanf("%s",P[i]);
            aho.insert(P[i],i);
        }

        aho.getFail();

        scanf("%s",text);
        aho.find(text);

        int ans = -1;
        for(int i=1; i <= n; i++) 
            if(aho.cnt[i]>ans) ans = aho.cnt[i];
        
        printf("%d\n",ans);

        for(int i=1; i <= n; i++)
            if(aho.cnt[i]==ans)
                printf("%s\n",P[i]);
    }
    return 0;
}

 

posted @ 2017-08-21 11:34  小草的大树梦  阅读(134)  评论(0编辑  收藏  举报