ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

字典树

2022-05-14 16:31:24  阅读:147  来源: 互联网

标签:cnt int son ++ str root 字典


tire 字典树

先来个模板

142. 前缀统计 - AcWing题库

什么是字典树呢?

就是存字典的树嘛,差不多的赶脚。

确实是将所有字符存入其中,方便查找(多是查找前缀)。怎么存捏?如下图

trie

建树

差不多是这个意思,但并非是把所有字符的空间给开出来,这就要讲到如何建树了。

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<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

标签:cnt,int,son,++,str,root,字典
来源: https://www.cnblogs.com/huaziqi/p/16270502.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有