HDU1671 Phone List 题解 字典树
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1671
题目大意,有T组数据,每组数据给你n个长度不超过10的字符串(n不超过10000),问在其中其否存在一个字符串是另一个字符串的前缀。
(我这里把两个相同的字符串也作为前缀了,不过数据应该是没有的)
解题思路:字典树。路径上的点cnt设为1,最后一个点cnt设为2。
如果在路径上碰到了cnt==2的点,或者最后一个点上之前就是cnt>0的。则说明存在前缀。
注意一点:主函数里调用构造函数占用的是栈内存,会MLE。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000010;
struct Trie {
int son[10], cnt;
void clean() { //Trie() {
memset(son, 0, sizeof(son));
cnt = 0;
}
} trie[maxn];
int sz;
void init() {
sz = 0;
trie[++sz].clean();
}
bool Insert(char *s) {
int x = 1;
while (*s) {
int id = *s - '0';
if (!trie[x].son[id]) {
// trie[++sz] = Trie();
trie[++sz].clean();
trie[x].son[id] = sz;
}
x = trie[x].son[id];
if (trie[x].cnt == 2) return true;
s ++;
if (*s) trie[x].cnt = 1;
else {
if (trie[x].cnt != 0) return true;
else trie[x].cnt = 2;
}
}
return false;
}
char s[10010][11];
int T, n;
int main() {
scanf("%d", &T);
while (T --) {
init();
scanf("%d", &n);
for (int i = 0; i < n; i ++) scanf("%s", s[i]);
bool flag = true;
for (int i = 0; i < n; i ++) {
if (Insert(s[i])) {
flag = false;
break;
}
}
puts(flag ? "YES" : "NO");
}
return 0;
}