LA 4670 Dominating Patterns (AC自动机)

Posted dwtfukgv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LA 4670 Dominating Patterns (AC自动机)相关的知识,希望对你有一定的参考价值。

题意:给定n个字符串和一个文本串,查找哪个字符串出现的次数的最多。

析:一匹配多,很明显是AC自动机。只需要对原来的进行修改一下,就可以得到这个题的答案,

计算过程中,要更新次数,并且要映射字符串。如果用KMP肯定会超时。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <string>
#include <queue>

using namespace std;
const int maxn = 1000000 + 5;
const int sigma = 26;
const int maxnode = 70 * 150 + 5;
map<string, int> ms;
//AC自动机
struct AhoCorasickAutomata{
    int cnt[155];
    int ch[maxnode][sigma];
    int f[maxnode];//失配函数
    int val[maxnode];//每个字符串结尾都有一个非0的val
    int last[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[s] = v;
    }
    //查找字符串
    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]);
        }
    }
    //获得失配函数
    int getFail(){
        queue<int> q;
        f[0] = 0;
        //初始化队列
        for(int c = 0; c < sigma; ++c){
            int u = ch[0][c];
            if(u){ f[u] = 0; q.push(u);  last[u] = 0; }
        }
        //bfs
        while(!q.empty()){
            int r = q.front();  q.pop();
            for(int c = 0; c < sigma; ++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]];
            }
        }
    }

};

AhoCorasickAutomata ac;
char text[maxn], p[155][75];

int main(){
    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", text);
        ac.find(text);
        int m = -1;
        for(int i = 1; i <= n; ++i)
            m = max(m, ac.cnt[i]);
        printf("%d\n", m);

        for(int i = 1; i <= n; ++i)
            if(ac.cnt[ms[p[i]]] == m)  printf("%s\n", p[i]);

    }
    return 0;
}

 

以上是关于LA 4670 Dominating Patterns (AC自动机)的主要内容,如果未能解决你的问题,请参考以下文章

LA 4670 Dominating Patterns (AC自动机)

LA_4670_Dominating_Patterns_(AC自动机+map)

UvaLive 4670 Dominating Patterns

UVALive 4670 Dominating Patterns

UVALive-4670 Dominating Patterns / 洛谷 3796 模板AC自动机

UVa Live 4670 Dominating Patterns - Aho-Corasick自动机