zoukankan      html  css  js  c++  java
  • AC自动机

    文本串中出现次数最多的模式串

    //LA4670, 洛谷3796
    %:pragma GCC optimize("Ofast", 2)
    #include <queue>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define maxn 12005
    int t, n, m, len, ans;
    int cnt[155], fail[maxn];
    int val[maxn], ch[maxn][26];
    char text[1000005], s[155][80];
    void init(){
        ans = 0;
        memset(ch, 0, sizeof(ch));
        fill(fail, fail+maxn, 0);
        fill(val, val+maxn, 0);
        fill(cnt, cnt+155, 0);
    }
    void s_insert(char *s, int v){ //构建字典树
        int now, root = 0;
        len = strlen(s);
        for(int i = 0; i < len; i ++){
            now = s[i]-'a';
            if(!ch[root][now]){
                ch[root][now] = ++ans;
            }
            root = ch[root][now];
        }
        val[root] = v;
    }
    void get_fail(){ //获取失配指针
        queue<int>Q;
        int u, now = 0;
        for(int i = 0; i < 26; i ++){
            if(ch[now][i]){ //将模式串的首字母序号加入队列
                Q.push(ch[now][i]);
                //fail[ch[now][i]] = 0;
                //last[ch[now][i]] = 0;
            }
        }
        while(!Q.empty()){
            now = Q.front(); Q.pop();
            for(int i = 0; i < 26; i ++){
                u = ch[now][i];
                if(u){ //当前序列存在
                    fail[u] = ch[fail[now]][i]; //失配指针指向其父节点失配指针指向节点的子节点
                    Q.push(ch[now][i]);
                }else{
                    ch[now][i] = ch[fail[now]][i]; //指向失配指针指向节点子节点
                }
            }
        }
    }
    void query(char *text){
        len = strlen(text);
        int now = 0;
        for(int i = 0; i < len; i ++){
            now = ch[now][text[i]-'a'];
            for(int j = now; j; j = fail[j]){
                cnt[val[j]]++;
            }
        }
    }
    int main(){
        while(scanf("%d", &n) && n){
            init();
            for(int i = 1; i <= n; i ++){
                scanf("%s", s[i]);
                s_insert(s[i], i);
            }
            scanf("%s", text);
            get_fail();
            query(text);
            int res = 0;
            for(int i = 1; i <= n; i ++){
                res = max(res, cnt[i]);
            }
            printf("%d
    ", res);
            for(int i = 1; i <= n; i ++){
                if(cnt[i] == res)
                    printf("%s
    ", s[i]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【BZOJ1835】[ZJOI2010]base 基站选址 线段树+DP
    【BZOJ1786】[Ahoi2008]Pair 配对 DP
    【BZOJ3956】Count 主席树+单调栈
    【BZOJ4605】崂山白花蛇草水 权值线段树+kd-tree
    【BZOJ2597】[Wc2007]剪刀石头布 最小费用流
    前端学习笔记之CSS属性设置
    前端学习笔记之HTML body内常用标签
    前端学习笔记之CSS介绍
    前端学习笔记之CSS选择器
    博客园美化技巧汇总
  • 原文地址:https://www.cnblogs.com/microcodes/p/12319330.html
Copyright © 2011-2022 走看看