【模板】AC自动机(加强版) 洛谷3796 AC自动机

题目

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

分析

改一改

code

#include
#include
#include
#include
#include
#include
#include

using namespace std;

struct Tree{
    int fail,from;
    int vis[26];
    int num;
}ac[1000000];
int n;
int cnt=0;

int w[1000000];
string ss[500];

void Build(string s,int x)
{
    int l=s.length();
    int now=0;
    for(int i=0;iif(ac[now].vis[s[i]-'a']==0) ac[now].vis[s[i]-'a']=++cnt;
        now=ac[now].vis[s[i]-'a'];
    }
    ac[now].num+=1; 
    ac[now].from=x;
}

void Get_fail()
{
    queue<int> Q;
    for(int i=0;i<26;++i)
    {
        if(ac[0].vis[i]!=0)
        {
            ac[ac[0].vis[i]].fail=0;
            Q.push(ac[0].vis[i]);
        }
    }
    while(!Q.empty()) 
    {
        int u=Q.front();
        Q.pop();
        for(int i=0;i<26;++i)
        {
            if(ac[u].vis[i]!=0)
            {
                ac[ac[u].vis[i]].fail=ac[ac[u].fail].vis[i];
                Q.push(ac[u].vis[i]);
            }
            else ac[u].vis[i]=ac[ac[u].fail].vis[i];
        }
    }
}

void ac_Query(string s)
{
    int l=s.length();
    int now=0,ans=0;
    for(int i=0;i'a'];
        for(int t=now;t&&(ac[t].num!=-1);t=ac[t].fail)
        {
            if (ac[t].from!=0) w[ac[t].from]++;
            //ac[t].num=-1;
        } 
    }
    for (int i=1;i<=n;i++)
    {
        if (w[i]>ans) ans=w[i];
    }
    printf("%d\n",ans);
    for (int i=1;i<=n;i++)
    {
        if (w[i]==ans) cout<int main()
{
    scanf("%d",&n);
    while (n){
    memset(ac,0,sizeof(ac));
    memset(w,0,sizeof(w));
    cnt=0;
    w[0]=0;
    for(int i=1;i<=n;++i)
    {
        string s;
        cin>>s;
        ss[i]=s;
        Build(s,i);
    }
    ac[0].fail=0;
    Get_fail();
    string s;
    cin>>s;
    ac_Query(s);
    scanf("%d",&n);
    }
}

你可能感兴趣的:(c++,洛谷,AC自动机)