zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    
            for(int i=1; i <= n; i++)
                if(aho.cnt[i]==ans)
                    printf("%s
    ",P[i]);
        }
        return 0;
    }
  • 相关阅读:
    第四章、Vue组件
    第三章、Vue实例
    第二章、Vue指令
    Python练习实例012
    Python练习实例011
    Python练习实例010
    Python练习实例009
    Python练习实例008
    Python练习实例007
    Python练习实例006
  • 原文地址:https://www.cnblogs.com/TreeDream/p/7403459.html
Copyright © 2011-2022 走看看