字典树
tire 字典树
先来个模板
142. 前缀统计 - AcWing题库
什么是字典树呢?
就是存字典的树嘛,差不多的赶脚。
确实是将所有字符存入其中,方便查找(多是查找前缀)。怎么存捏?如下图
建树
差不多是这个意思,但并非是把所有字符的空间给开出来,这就要讲到如何建树了。
void insert()
{
int root = 0;
for (int i = 0; str[i]; i ++)
{
int s = str[i] - 'a';
if(!son[root][s]) son[root][s] = ++ idx;
root = son[root][s];
}
cnt[root]++;
}
root 节点设为0。son{ root }{ s }表示root这个节点上的s的编号idx。倘若这个点没有被创建,那就 son{ root }{ s } = ++ idx; 感觉这个 root 有并查集那味儿。存储他儿子的编号,便于查找。这时候就有读者要问,这个cnt{ N }是干嘛用的呢?答案是记录以这个点为结尾的数量。在搜前缀时,不一定只有一个字符从这里结束,所以要记录一下数量。
搜索
int search()
{
int root = 0, res = 0;
for(int i = 0; str[i]; i ++)
{
int s = str[i] - 'a';
if(!son[root][s]) break;
root = son[root][s];
res += cnt[root];
}
return res;
}
如果说下面没有节点了就直接break掉。并且这里cnt数组派上用场了。res每次加一个cnt{ root }.最后返回答案。
2022-5-12 21:09:37
进阶
AcWing 161. 电话列表 - AcWing
给出一个电话列表,如果列表中存在其中一个号码是另一个号码的前缀这一情况,那么就称这个电话列表是不兼容的。
假设电话列表如下:
Emergency 911
Alice 97 625 999
Bob 91 12 54 26
在此例中,报警电话号码(911
)为 Bob 电话号码(91 12 54 26
)的前缀,所以该列表不兼容。
输入格式
第一行输入整数 t,表示测试用例数量。
对于每个测试用例,第一行输入整数 n,表示电话号码数量。
接下来 n 行,每行输入一个电话号码,号码内数字之间无空格,电话号码不超过 10 位。
输出格式
对于每个测试用例,如果电话列表兼容,则输出 YES
。
否则,输出 NO
。
数据范围
1≤t≤40,
1≤n≤10000
输入样例:
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
输出样例:
NO
YES
跟模板差不多,只不过在搜的时候要一个一个搜,并且它并非求前缀的数量,所以用bool判断就好了。
#include
#include
#include
using namespace std;
#define N 500010
#define M 1000010
int n, m, f;
int son[N][30], idx, cnt[N], T;
char str[M][15];
void insert(char *s)
{
int root = 0;
for (int i = 0; s[i]; i ++)
{
int st = s[i] - '0';
if(!son[root][st]) son[root][st] = ++ idx;
root = son[root][st];
cnt[root]++;
}
}
bool search(char *s)
{
int root = 0;
for(int i = 0; s[i]; i ++)
{
int st = s[i] - '0';
if(cnt[son[root][st]]==1) return false;
root = son[root][st];
}
return true;
}
int main()
{
scanf("%d", &T);
while(T --)
{
f=0;
idx=0;
memset(son[0],0,sizeof son);
memset(cnt,0,sizeof cnt);
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%s", str[i]);
insert(str[i]);
}
for (int i = 0; i < n; i++)
{
if(search(str[i]))
{
f=1;
break;
}
}
if(f == 1) puts("NO");
else puts("YES");
}
return 0;
}
2022-5-12 21:34:32