• 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
    ", m);
    
            for(int i = 1; i <= n; ++i)
                if(ac.cnt[ms[p[i]]] == m)  printf("%s
    ", p[i]);
    
        }
        return 0;
    }
    
  • 相关阅读:
    06 继承与多态
    动手动脑 4 String 类
    字串加密
    课后作业(查询类对象创建个数)
    动手动脑 3 类与对象
    动手动脑 (第二次)
    IOS 网络判断
    ios常用的几个动画代码
    iOS Get方式带中文不能请求网络
    UILabel Text 加下划线
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/5558633.html
Copyright © 2020-2023  润新知