字典树
tire 字典树
先来个模板
什么是字典树呢?
就是存字典的树嘛,差不多的赶脚。
确实是将所有字符存入其中,方便查找(多是查找前缀)。怎么存捏?如下图

建树
差不多是这个意思,但并非是把所有字符的空间给开出来,这就要讲到如何建树了。
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
进阶
给出一个电话列表,如果列表中存在其中一个号码是另一个号码的前缀这一情况,那么就称这个电话列表是不兼容的。
假设电话列表如下:
Emergency 911Alice 97 625 999Bob 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<iostream>
#include<cstring>
#include<algorithm>
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
本文来自博客园,作者:huaziqi 转载请注明原文链接:https://www.cnblogs.com/huaziqi/p/16270502.html

                
            
        
浙公网安备 33010602011771号