Trie树学习记录

本文介绍了Trie树在不同场景下的应用案例,包括构建单词查找树解决COGS词链问题,处理15年前的NOI题目,以及实现有道搜索框的自动补全功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

真的不能再拒绝字符串算法的学习,先从Trie树学起吧。。。

COGS 词链,裸题,建出Trie树后遍历一遍,比较根到每个叶子节点的单词个数,取最大值;code:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
struct trie_node{
	char letter;
	int sum; bool f;
	trie_node *next[26];
	trie_node(char letter): letter(letter) {int i;for (i=0;i<=25;++i) next[i]=NULL; f=false; sum=0;}
};
trie_node *root;
char s[100];
char now[100];
int n,l;
void insert(trie_node *p,int i,int len)
{
	trie_node *temp;
	if (p->next[(int)(s[i])-97]==NULL)
	  {
	    temp=new trie_node(s[i]);
	    p->next[(int)(s[i])-97]=temp;
	    p=p->next[(int)(s[i])-97];
	  }
	else
	  p=p->next[(int)(s[i])-97];
	if (i==len-1)
	  {
	    p->f=true; p->sum++;
	    return;
	  }
	insert(p,i+1,len);
}
void count(trie_node *p)
{
	int i;
	if (p->f)
	  {
	    for (i=1;i<=l;++i)
	  	  printf("%c",now[i]);
	  	printf("%c ",p->letter);
	  	printf("%d\n",p->sum);
	  }
	for (i=0;i<=25;++i)
	  {
	    if (p->next[i])
	      {
	        if (p!=root)
	          {
	          	l++;
	            now[l]=p->letter;
	          }
			count(p->next[i]);
			if (p!=root)
			  l--;   
	      }
	  }
}
int main()
{
	int i,len;
	root=new trie_node(' ');
	scanf("%d",&n);
	for (i=1;i<=n;++i)
	  {
	    scanf("%s",&s);
	    len=strlen(s);
	    insert(root,0,len);
	  }
	l=0;
	count(root);
}
COGS 293 【NOI 2000】单词查找树

15年前的NOI题被各种乱虐,这个题大概可以和数字三角形一起哭死在墙角,code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct trie_node{
	char letter;
	trie_node *next[26];
	trie_node(char letter): letter(letter) {int i; for(i=0;i<=25;++i) next[i]=NULL;}
};
int ans=0;
trie_node *root;
char str[100];
void insert(trie_node *p,int i,int len)
{
	trie_node *temp;
	if (i==len) return;
	if (p->next[(int)(str[i])-'A']==NULL)
	  {
	    temp=new trie_node(str[i]);
		p->next[(int)(str[i])-'A']=temp;
		p=p->next[(int)(str[i])-'A'];  
	  }
	else
	  p=p->next[(int)(str[i])-'A'];
	insert(p,i+1,len);
}
void count(trie_node *p)
{
	bool f; int i;
	ans++;
	for (i=0;i<=25;++i)
	  if (p->next[i]!=NULL)
	    count(p->next[i]);
}
int main()
{
	int len;
	root=new trie_node(' ');
	while (scanf("%s",&str)==1)
	  {
	    len=strlen(str);
	    insert(root,0,len);
	  }
	count(root);
	printf("%d\n",ans);
}
COGS 647 【Youdao2010】有道搜索框 

一道思路清晰但代码不是特别好写 code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct trie_node{
	char letter;
	bool f; 
	trie_node *next[26];
	trie_node(char letter): letter(letter) {int i;for (i=0;i<=25;++i) next[i]=NULL; f=false;}
};
int n,t=0,m,l;
trie_node *root;
char now[5000];
char str[5000];
void insert(trie_node *p,int i,int len)
{
	trie_node *temp;
	if (p->next[(int)(str[i])-97]==NULL)
	  {
	    temp=new trie_node(str[i]);
	    p->next[(int)(str[i])-97]=temp;
	    p=p->next[(int)(str[i])-97];
	  }
	else
	  p=p->next[(int)(str[i])-97];
	if (i==len-1)
	  {
	    p->f=true;
	    return;
	  }
	insert(p,i+1,len);
}
bool work(trie_node *p,int i,int len)
{
	if (i==len) return true;
	if (p->next[(int)(str[i])-97]==NULL)
	  return false;
	else
	  work(p->next[(int)(str[i])-97],i+1,len);
}
void out(trie_node *p,int i,int len)
{
	int j;
	if (i<=len-1)
	  out(p->next[(int)(str[i])-97],i+1,len);
	if (i>=len)
	  {
	  	if (p->f&&t<8)
	      {
		    for (j=0;j<l;++j) 
		      cout<<now[j]; 
		    if (i!=len)
			  cout<<p->letter;
			cout<<' ';
			t++;
		  }
	    for (j=0;j<=25;++j)
	      {
	        if (p->next[j]!=NULL&&t<8)
	          {
	          	if (i>len)
	          	  {
	                now[l]=p->letter;
	                l++;
	              }
	            out(p->next[j],i+1,len);
	            if (i>len)
	              l--;
	          }
	      } 
	  }
}
int main()
{
	int i,len;
	root=new trie_node(' ');
	scanf("%d",&n);
	for (i=1;i<=n;++i)
	  {
	    scanf("%s",&str);
	    len=strlen(str);
	    insert(root,0,len);
	  }
	scanf("%d",&m);
	for (i=1;i<=m;++i)
	  {
	    scanf("%s",&str);
	    len=strlen(str);
	    if (!work(root,0,len))
	      printf("%s\n",str);
	    else
	      {strcpy(now,str); l=len; t=0; out(root,0,len); printf("\n");}
	  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值