洛谷P2580 于是他错误的点名开始了 题解 字典树

题目链接:https://www.luogu.com.cn/problem/P2580

解题思路:

对于前 \(n\) 次插入操作,使用字典树模拟,并且标记字符串最后一个字符对应节点的 \(cnt=1\)

对于后 \(m\) 次查询操作,我们首先查询是否存在该字符串,如果字典树路径都走不通,那么肯定没有;如果最后一个节点对应的 \(cnt=0\),那么也没有,都输出“WRONG”。

如果最后一个节点对应的 \(cnt=1\),则说明是第一次碰到,输出“OK”,然后将给节点的 \(cnt\) 更新为 \(2\)

如果最后一个节点对应的 \(cnt=2\),说明重复了,输出“REPEAT”。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 500050;
struct Trie {
    int son[26];
    int cnt;
    Trie() {
        memset(son, 0, sizeof(son));
        cnt = 0;
    }
} trie[maxn];
int sz, n, m;
char s[55];
void init() {
    sz = 1;
}
void Insert(char *s) {
    int x = 1;
    while (*s) {
        int id = *s - 'a';
        if (!trie[x].son[id]) {
            trie[x].son[id] = ++sz;
        }
        x = trie[x].son[id];
        s ++;
    }
    trie[x].cnt = 1;
}
int check(char *s) {
    int x = 1;
    while (*s) {
        int id = *s - 'a';
        if (!trie[x].son[id]) return 0;
        x = trie[x].son[id];
        s ++;
    }
    if (trie[x].cnt == 0) {
        return 0;
    }
    else if (trie[x].cnt == 1) {
        trie[x].cnt = 2;
        return 1;
    }
    else return 2;
}
int main() {
    init();
    cin >> n;
    while (n --) {
        cin >> s;
        Insert(s);
    }
    cin >> m;
    while (m --) {
        cin >> s;
        int res = check(s);
        if (res == 0) puts("WRONG");
        else if (res == 1) puts("OK");
        else puts("REPEAT");
    }
    return 0;
}
posted @ 2020-03-26 18:29  quanjun  阅读(127)  评论(0编辑  收藏  举报