【字典树】知识点讲解 模板+例题x1

这里的讲解超级棒!!必戳!:https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html

其中最重要的是字典树数组写法:s[i][j]=k,表示编号为i的节点的第j个孩子是编号为k的节点

我的理解就是觉得,如果字符串的数量一大起来,题意是关于查询“相同前缀”的,那么就用字典树了!!!


模板


更多模板请见链接。


例题:糟糕的Bug



大致思路

找相同前缀的字符串。。字典树模板题。。

这里的关键在于是要无视各个字符串的输入顺序,所以可能前面输的字符串包含了后面的,也可能后面的包含了前面的。

针对这个问题,就注意两个思路:

    ①如果当前输入的包含了前面的,那么在插入当前字符串的时候,会达到前面的叶子结点&&没有新开结点(即一直用的是前面的结点)。

    ②如果当前输入的被前面的包含了,那么在插入当前字符串,插入完成之后,没有新开结点。

有了这俩思路,就知道判断语句怎么写了。需要用一个e[maxn],e[k]表示第k个结点是否为叶子结点。需要在插入过程中通过判断temp==tot来看有没有新开结点。


AC代码

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn=566666;
int s[maxn][26];
bool e[maxn];
int tot=0;

void init()
{
	memset(s,-1,sizeof(s));
	memset(e,false,sizeof(e));
} 

bool insert(char *t,int len) //传入的字符串和其长度 
{
	int temp=tot;
	int p=0;
	for(int i=0;i<len;i++)
	{
		if(s[p][t[i]-'a']==-1) s[p][t[i]-'a']=++tot;
		p=s[p][t[i]-'a'];   //之前这里想当然的写成p=tot,不对!!因为如果没有新开结点呢?
		if(e[p]==true && tot==temp) return false;
	}
	if(tot==temp) return false;
	e[p]=true;
	return true; 
}


int main()
{
	init();
	int n;
	cin>>n;
	bool flag=true;
	while(n--)
	{
		char t[12];
		scanf("%s",t);
		if(flag)
			flag=insert(t,strlen(t));
	}
	if(flag==true)
		cout<<"Good Luck!";
	else
		cout<<"Bug!";
	return 0;
}



猜你喜欢

转载自blog.csdn.net/m0_38033475/article/details/80315611
x1
今日推荐