http://acm.hdu.edu.cn/showproblem.php?pid=2222

 

注意:

1. keyword可以相同,因此计算时要累计:cur->num++。

2. 同一个keyword在str中出现多次的话,只计算一次,所以算过后需要将num设为-1(表示已经计算了)。

对于

2
5
she
he
say
shr
her
yasherhs
5
she
he
say
sher
her
yasherhs

sher中包含:she,he,her,sher四个关键字,计算顺序:she->he->e->sher->her。

注意:匹配到一个关键字,需要继续把这个keyword中包含的其他的短的keyword都匹配了,再继续前移。

# include <cstdio>
#include <stdlib.h>
#include "memory.h"
#include "queue"

const int MAX_N = 1000010;

char s[MAX_N];

struct TNode {
    int num;
    TNode *suffix;
    TNode *next[26];
    TNode() {
        clean();
    }
    void clean() {
        num = 0;
        suffix = NULL;
        memset(next, NULL, sizeof next);
    }
};

TNode *T[MAX_N];

int pos = 0;

void buildTrie(char *str) {
    TNode * cur = T[0];
    for (int i = 0; str[i]; ++i) {
        int c = str[i] - 'a';
        if (cur->next[c] == NULL) {
            if (T[++pos] == NULL) {
                T[++pos] = new TNode();
            }
            cur->next[c] = T[pos];
        }
        cur = cur->next[c];
    }
    cur->num++;
}

void addSuffix() {
    TNode* root = T[0];
    root->suffix = root;
    std::queue<TNode*> qTrie;
    for (int i = 0; i < 26; ++i) {
        if (root->next[i] == NULL) {
            root->next[i] = root;
        } else {
            root->next[i]->suffix = root;
            qTrie.push(root->next[i]);
        }
    }
    TNode *cur, *suf;
    while (!qTrie.empty()) {
        cur = qTrie.front(), qTrie.pop();
        suf = cur->suffix;
        for (int i = 0; i < 26; ++i) {
            if (cur->next[i] == NULL) {
                cur->next[i] = suf->next[i];
            } else {
                cur->next[i]->suffix = suf->next[i];
                qTrie.push(cur->next[i]);
            }
        }
    }
}

int query(char *str) {
    int ans = 0;
    TNode * cur = T[0];
    for (int i = 0; str[i]; ++i) {
        int c = str[i] - 'a';
        cur = cur->next[c];
        TNode * back = cur;

        while (back != T[0] && back->num != -1) {
//            printf("%c %d\n", str[i], back->num);
            ans += back->num;
            back->num = -1;
            back = back->suffix;
        }
    }
    return ans;
}

void clean() {
    for (int i = 0; i <= pos; ++i) {
        if (T[i] != NULL) {
            T[i]->clean();
        }
    }
    pos = 0;
}


int main() {
    if (freopen("/Users/fripside/ClionProjects/cc150/input", "r", stdin) == NULL) {
        fprintf(stderr, "error redirecting stdout\n");
    }
    T[0] = new TNode;
    int c, t;
    scanf("%d", &c);
    while (c--) {
        clean();
        scanf("%d", &t);
        while (t--) {
            scanf("%s", s);
            buildTrie(s);
        }
        addSuffix();
        scanf("%s", s);
        printf("%d\n", query(s));
    }
    return 0;
}