洛谷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;
}