Luo Gu -P3796-AC automaton enhanced version

link:

https://www.luogu.org/problem/P3796

Meaning of the questions:

NN has a pattern consisting of a string of small letters and a text string TT. Each mode string may appear in multiple text string. You need to find out which mode the maximum number of strings appear in the text string in TT.

Ideas:

Each end node of the trie template record corresponding to the string of numerals, the number of matching records.

Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
//#include <memory.h>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <stack>
#include <string>
#include <assert.h>
#include <iomanip>
#include <iostream>
#include <sstream>
#define MINF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN = 2e6+10;

struct Trie
{
    int Next[26];
    int End;
    int Fail;
    void Init()
    {
        memset(Next, 0, sizeof(Next));
        End = Fail = 0;
    }
}trie[MAXN];
int cnt, n, pos, maxt;
int Ans[MAXN];
char s[MAXN], Pt[200][100];

void Insert(char *t, int id)
{
    int len = strlen(t);
    int p = 0;
    for (int i = 0;i < len;i++)
    {
        if (trie[p].Next[t[i]-'a'] == 0)
        {
            trie[p].Next[t[i]-'a'] = ++cnt;
            trie[cnt].Init();
        }
        p = trie[p].Next[t[i]-'a'];
    }
    trie[p].End = id;
}

void BuildAC()
{
    queue<int> que;
    for (int i = 0;i < 26;i++)
    {
        if (trie[0].Next[i] != 0)
            que.push(trie[0].Next[i]);
    }
    while (!que.empty())
    {
        int u = que.front();
        que.pop();
        for (int i = 0;i < 26;i++)
        {
            if (trie[u].Next[i])
            {
                trie[trie[u].Next[i]].Fail = trie[trie[u].Fail].Next[i];
                que.push(trie[u].Next[i]);
            }
            else
                trie[u].Next[i] = trie[trie[u].Fail].Next[i];
                //压缩路径, 没有的点直接指向别的节点, 减少向上找的时间
        }
    }
}

void Query(char *qs)
{
    int len = strlen(qs);
    int p = 0;
    for (int i = 0;i < len;i++)
    {
        p = trie[p].Next[qs[i]-'a'];
        for (int j = p;j != 0 && trie[j].End != -1;j = trie[j].Fail)
        {
            //将所有能出现的匹配都跑一遍, 同时处理防止多跑.
            if (trie[j].End != 0)
            {
                Ans[trie[j].End]++;
                maxt = max(maxt, Ans[trie[j].End]);
            }
        }
    }
}

int main()
{
    while (~scanf("%d", &n) && n)
    {
        memset(Ans, 0, sizeof(Ans));
        cnt = pos = maxt = 0;
        trie[0].Init();
        for (int i = 1;i <= n;i++)
        {
            scanf("%s", Pt[i]);
            Insert(Pt[i], i);
        }
        scanf("%s", s);
        BuildAC();
        Query(s);
        if (maxt <= 0)
            puts("0");
        else
        {
            printf("%d\n", maxt);
            for (int i = 1;i <= n;i++)
            {
                if (Ans[i] == maxt)
                    puts(Pt[i]);
            }
        }
    }

    return 0;
}

Guess you like

Origin www.cnblogs.com/YDDDD/p/11610431.html