zoukankan      html  css  js  c++  java
  • AC自动机(加强版)

    题目描述

    NN个由小写字母组成的模式串以及一个文本串TT。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串TT中出现的次数最多。

    输入输出格式

    输入格式:

    输入含多组数据。

    每组数据的第一行为一个正整数NN,表示共有NN个模式串,1 leq N leq 1501N150。

    接下去NN行,每行一个长度小于等于7070的模式串。下一行是一个长度小于等于10^6106​​的文本串TT。

    输入结束标志为N=0N=0。

    输出格式:

    对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。

    输入输出样例

    输入样例#1:
    2
    aba
    bab
    ababababac
    6
    beta
    alpha
    haha
    delta
    dede
    tata
    dedeltalphahahahototatalpha
    0
    输出样例#1:
    4
    aba
    2
    alpha
    haha


    ac自动机,last指针版
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int  maxn = 100001;
    int n;
    char s[maxn][101];
    char ss[maxn*10];
    int ans=0;
    struct Aho_Corasick_automato {
        int sz;
        int ch[maxn][26];
        int cnt[maxn];
        int val[maxn];
        int last[maxn];
        int fail[maxn];
        int num;
        void init() {
            memset(ch[0],0,sizeof(ch[0]));
            memset(cnt,0,sizeof(cnt));
            sz=1;
        }
        void insert(char *s,int num) {
            int len=strlen(s);
            int u=0;
            for(int i=0; i<len; ++i) {
                int v=(s[i]-'a');
                if(!ch[u][v]) {
                    memset(ch[sz],0,sizeof(ch[sz]));
                    val[sz]=0;
                    ch[u][v]=sz++;
                }
                u=ch[u][v];
            }
            val[u]=num;
        }
        void get_fail() {
            fail[0]=0;
            queue<int>que;
            for(int i=0; i<26; i++) {
                int u=ch[0][i];
                if(u) {
                    fail[u]=0;
                    que.push(u);
                }
            }
            while(!que.empty()) {
                int u=que.front();
                que.pop();
                for(int i=0; i<26; i++) {
                    int v=ch[u][i];
                    if(!v) {
                        ch[u][i]=ch[fail[u]][i];
                        continue;
                    }
                    que.push(v);
                    int k=fail[u];
                    fail[v]=ch[k][i];
                    last[v]=val[fail[v]] ? fail[v] : last[fail[v]];
                }
            }
        }
        void work(int x) {
            if(x) {
                cnt[val[x]]++;
                work(last[x]);
            }
        }
        void find(char *s) {
            int len=strlen(s);
            int u=0;
            for(int i=0; i<len; i++) {
                int v=(s[i]-'a');
                if(!ch[u][v])u=fail[u];
                while(u&&!ch[u][v])
                    u=fail[u];
                u=ch[u][v];
                if(val[u])
                    work(u);
                else if(last[u])
                    work(last[u]);
            }
        }
    } ac;
    
    int main() {
    
    
        while(scanf("%d",&n)==1&&n!=0) {
            ac.init();
            for(int i=1; i<=n; i++) {
                scanf("%s",s[i]);
                ac.insert(s[i],i);
            }
            ac.get_fail();
            scanf("%s",ss);
            ac.find(ss);
            int ans=0,r;
            for(int i=1;i<=n;i++)
                if(ac.cnt[i]>ans)ans=ac.cnt[i],r=i;;
            printf("%d
    ",ans);
             for(int r=1;r<=n;r++)
                if(ac.cnt[r]==ans)
                    printf("%s
    ",s[r]);
            }
        return 0;
    }


  • 相关阅读:
    3、linux网络编程--网络字节序
    1、linux网络编程--网络协议
    第四篇:进程
    第五篇:进程通信
    第六篇:线程原理
    操作系统基本概念
    第一篇:基础原理篇
    第二篇:操作系统历史
    (2)linux下的简单的socket通信实例
    (3)基于linux的socket编程TCP半双工client-server聊天程序
  • 原文地址:https://www.cnblogs.com/sssy/p/7259284.html
Copyright © 2011-2022 走看看