zoukankan      html  css  js  c++  java
  • 【AC自动机】Lougu P3796

    题目描述

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

    输入输出格式

    输入格式:

    输入含多组数据。

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

    接下去NNN行,每行一个长度小于等于707070的模式串。下一行是一个长度小于等于10610^6106的文本串TTT。

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

    输出格式:

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

    输入输出样例

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

    题解

    写个AC自动机的板子上来。。。

    反正就是先建一棵trie树,然后bfs找失配指针(类似KMP)。。。

    然后再在上面搞些奇奇怪怪的东西。。。

    代码

    //by 减维
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<map>
    #include<bitset>
    #include<algorithm>
    #define ll long long
    #define maxn 1000005
    using namespace std;
    
    struct trie{
        int end,fail,to[26];
        void cle(){
            memset(to,0,sizeof(to));
            end=fail=0;
        }
    }ac[maxn];
    
    struct anss{
        int pos,num;
    }ans[maxn];
    
    int n,tot;
    string s[155];
    
    bool cmp(const anss&x,const anss&y)
    {
        if(x.num==y.num)return x.pos<y.pos;
        return x.num>y.num;
    }
    
    void build(int x)
    {
        int now=0,ch;
        int len=s[x].length();
        for(int i=0;i<len;++i)
        {
            ch=s[x][i]-'a';
            if(!ac[now].to[ch])ac[now].to[ch]=++tot,ac[tot].cle();
            now=ac[now].to[ch];
        }
        ac[now].end=x;
    }
    
    void getf()
    {
        queue<int>q;
        for(int i=0;i<26;++i)
            if(ac[0].to[i])q.push(ac[0].to[i]),ac[ac[0].to[i]].fail=0;
        while(!q.empty())
        {
            int d=q.front();
            q.pop();
            for(int i=0;i<26;++i)
            {
                int dd=ac[d].to[i];
                if(dd)ac[dd].fail=ac[ac[d].fail].to[i],q.push(dd);
                else ac[d].to[i]=ac[ac[d].fail].to[i];
            }
        }
    }
    
    void ask()
    {
        int now=0,ch;
        int len=s[0].length();
        for(int i=0;i<len;++i)
        {
            ch=s[0][i]-'a';
            now=ac[now].to[ch];
            for(int j=now;j;j=ac[j].fail)
                if(ac[j].end)ans[ac[j].end].num++;
        }
        sort(ans+1,ans+1+n,cmp);
        printf("%d
    ",ans[1].num);
        for(int i=1;i<=n;++i)
            if(ans[i].num==ans[1].num)cout<<s[ans[i].pos]<<endl;
            else break;
    }
    
    int main()
    {
        while(1)
        {
            scanf("%d",&n);
            if(n==0)return 0;
            tot=0;ac[0].cle();
            for(int i=1;i<=n;++i)
            {
                cin>>s[i];
                build(i);
                ans[i].pos=i;
                ans[i].num=0;
            }
            getf();
            cin>>s[0];
            ask();
        }
    }
  • 相关阅读:
    python爬取糗事百科段子
    python爬虫-韩寒新浪博客博文
    python-函数
    Python-列表
    Linux学习笔记001——win下安装Linux虚拟机
    python爬虫-正则表达式
    IIS使用十大原则,(IIS过期时间,IIS缓存设置) 【转载】
    在mysql 中两种锁定问题
    php 迭代器与和生成器
    DBCP连接池使用问题
  • 原文地址:https://www.cnblogs.com/rir1715/p/8006600.html
Copyright © 2011-2022 走看看