ac自动机(加强版)

题目描述

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
这题跟上一题不太一样,这题需要求的每个模式串块出现在文本串中的次数(出现次数)输出最多次数和该模式串(可能有多个),而上一题是询问文本串中出现了几个模式串(出现即可)
主要区别:在于color记上有点变动,因为还要输出模式串,再对每个模式串根据color进行insearch一下就ok
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <algorithm>
#include <iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <vector>
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF  0x3f3f3f3f
#define mod 1000000007
using namespace std;
typedef long long ll ;
const int N = 1000009 ;
int tree[N][27] , k , color[N];
char str[1000009];
char s[151][71];
char aa[151][71];
int cnt ;
int fail[N];
int max1 ;
int ans ;

void winsert(char *a)
{
    int p = 0 ;
    for(int i = 0 ; a[i] ; i++)
    {
        int c = a[i] - 'a';
        if(!tree[p][c]) tree[p][c] = ++k ;
        p = tree[p][c];
    }
    color[p] = 1 ;
}

void getfail()
{
    queue<int>q;
    int p = 0 ;
    for(int i = 0 ; i < 26 ; i++)
    {
        if(tree[p][i])
        {
            fail[tree[p][i]] = 0 ;
            q.push(tree[p][i]);
        }
    }
    while(!q.empty())
    {
        int next = q.front();
        q.pop();
        for(int i = 0 ; i < 26 ; i++)
        {
            if(tree[next][i])
            {
                fail[tree[next][i]] = tree[fail[next]][i];
                q.push(tree[next][i]);
            }
            else
            {
                tree[next][i] = tree[fail[next]][i];
            }
        }
    }

}

void query()
{
    int p = 0 ;
    for(int i = 0 ; str[i] ; i++)
    {
        p = tree[p][str[i] - 'a'];
        for(int j = p ; j  ; j = fail[j])
        {
            if(color[j])
            {
                color[j]++;
                if(color[j] - 1 > max1)//注意要减一,因为本身为1.
                    max1 = color[j] - 1;
            }
        }
    }
}

void winsearch(char *a)
{
    int p = 0 ;
    for(int i = 0 ; a[i] ; i++)
    {
        int c = a[i] - 'a';
        if(!tree[p][c]) return ;
        p = tree[p][c];
    }
    if(color[p] - 1 >= max1)
    {
        strcpy(aa[cnt++] , a);
    }

}

int main()
{
    int n ;
    while(~scanf("%d" , &n) && n)
    {
        memset(tree , 0 , sizeof(tree));
        memset(color , 0 , sizeof(color));
        max1 = 0 ;
        cnt = 0 ;
        k = 0 ;

        for(int i = 0 ; i < n ; i++)
        {
            scanf("%s" , s[i]);
            winsert(s[i]);
        }
        getfail();
        scanf("%s" , str);
        query();
        for(int i = 0 ; i < n ; i++)
        {
            winsearch(s[i]);
        }
        printf("%d
" , max1);
        for(int i = 0 ; i < cnt ; i++)
        {
            printf("%s
" , aa[i]);
        }

    }

    return 0 ;
}
原文地址:https://www.cnblogs.com/nonames/p/11360708.html