字典树,顾名思义,就是一种对字母等字符串进行处理的一种特殊数据结构。说白了,就是二十六叉树。定义一个头指针,每次从头指针开始操作。
有两种常用的操作:
1.查询某个字符串的出现次数。
每个节点的count置为0,直到这个字符串结束,在末尾处count++.这样,就记录了该字符串的出现次数。
2.查询某个字符串特定序列出现的次数。
每个节点的count初始化为0,当读入一个字符,则count++。这样,查询时,这个节点count记录的就是从头结点到该结点特定序列出现的次数。可以用于统计单词的前缀一类的题目。
例题:
给你一堆英文单词(可能有4000000个。用普通查询铁定让你TLE)。找出出现次数最多的,输出这个单词,并输出出现的次数。
思路:
如果数据范围很小,我们可以用STL里面的map映射来做,但是数据范围太大,用普通的数据结构肯定会超时,所以要考虑更优的数据结构。当然,这题也是赤裸裸的字典树应用。当然,也可以用hash来做。懒的写了,参考学长代码
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N=2*1e5+10;
int n,m,q,k,ans,sum,top;
char ch1[N],ch2[N];
struct Dictree///字典树
{
int count;///单词出现次数
struct Dictree *tree[26];///26个子节点
}*a;
void init()
{
a=new Dictree;
for(int i=0; i<26; ++i) ///子节点置空
{
a->tree[i]=NULL;
}
}
int insert(char str[])
{
int len,j;
Dictree *head=a;///head是头指针
len=strlen(str);
for(int i=0; i<len; ++i)
{
j=(int)(str[i]-'a');
if(head->tree[j]==NULL)
{
head->tree[j]=new Dictree;
head=head->tree[j];
head->count=0;
for(int k=0; k<26; k++)
{
head->tree[k]=NULL;
}
}
else head=head->tree[j];
}
head->count++;
return head->count;
}
int main()
{
int num,maxx=0;
init();
scanf("%d",&num);
for(int i=0; i<num; ++i)
{
scanf("%s",ch1);
int ans=insert(ch1);
if(ans>maxx)
{
maxx=ans;
strcpy(ch2,ch1);
}
}
printf("%s %d\n", ch2,maxx);
}
数据范围较小,可用map映射
#include <bits/stdc++.h>
using namespace std;
const int N=2*1e5+10;
int n,m,q,k,ans,sum,top;
char ch1[N],ch2[N];
map<string,int>dictree;
int main()
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%s",ch1);
dictree[ch1]++;///每个单词出现次数
}
map<string,int >::iterator ita,itb;
for(ita=dictree.begin(),itb=dictree.begin(); ita!=dictree.end(); ++ita)
{
if(ita->second>itb->second)
{
itb=ita;
}
}
cout<<itb->first<<" "<<itb->second<<endl;
return 0;
}原文地址:http://blog.csdn.net/u013050857/article/details/46533505