Luogu P3796 [Template] AC automata (enhanced version)

Topic

Insert picture description here

Input sample

2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0

Sample output

4
aba
2
alpha
haha

Title

  1. In fact, it is still AC automata template question (detailed explanation is in HDU2222). As long as you understand its core ne array, it is still relatively simple. This question is to find the number of times a word appears in the article and output it. This question needs to calculate the space Complexity, open the right size.
  2. The ne array represents the longest prefix in the dictionary tree that can be matched by a suffix ending at a certain point, then we are in the process of word matching in the article, when a word is matched successfully, then all the ne points of this word The position, the position pointed by ne of ne, can be matched successfully
  3. In this way, we only need to mark the node number of the end letter of each word when inserting, and then in the process of article matching, after each successful match, we will record the number of occurrences of each word by the node number just marked. , And finally traverse the largest value output

Code

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 160, M = 1e6 + 10, K = 155 * 75;

int n;
char s[M];
string str[N];
int tr[K][26], cnt[K], idx;
int q[K], ne[K];
int id[K], res[N];
int maxn;

void insert(int x) {
    
    
    int p = 0;
    for (int i = 0; s[i]; i++) {
    
    
        int u = s[i] - 'a';
        if (!tr[p][u]) tr[p][u] = ++idx;
        p = tr[p][u];
    }
    cnt[p]++;
    id[p] = x; //标记一下每个单词结尾字母的节点编号
}

void build() {
    
    

    int hh = 0, tt = -1;
    for (int i = 0; i < 26; i++) {
    
    
        if (tr[0][i]) q[++tt] = tr[0][i];
    }

    while (hh <= tt) {
    
    
        int t = q[hh++];
        for (int i = 0; i < 26; i++) {
    
    
            int p = tr[t][i];
            if (!p) tr[t][i] = tr[ne[t]][i];
            else {
    
    
                ne[p] = tr[ne[t]][i];
                q[++tt] = p;
            }
        }
    }

}

int main() {
    
    

    while (cin >> n, n) {
    
    

        memset(tr, 0, sizeof tr);
        memset(cnt, 0, sizeof cnt);
        memset(ne, 0, sizeof ne);
        memset(id, 0, sizeof id);
        memset(res, 0, sizeof res);
        idx = 0, maxn = 0;

        for (int i = 1; i <= n; i++) {
    
    
            cin >> s;
            str[i] = s;
            insert(i);
        }

        build();

        cin >> s;

        for (int i = 0, j = 0; s[i]; i++) {
    
    
            int t = s[i] - 'a';
            j = tr[j][t];

            int p = j;
            while (p) {
    
    
                //通过节点编号找对应的单词,然后累加它出现的次数
                res[id[p]] += cnt[p];
                p = ne[p];
            }
        }
        for (int i = 1; i <= n; i++) maxn = max(res[i], maxn);

        cout << maxn << endl;
        for (int i = 1; i <= n; i++) {
    
    
            if (res[i] == maxn) {
    
    
                cout << str[i] << endl;
            }
        }
    }

    return 0;
}

Guess you like

Origin blog.csdn.net/qq_44791484/article/details/113802457