辉爷:Trie树的实现
v_JULY_v:从Trie树(字典树)谈到后缀树(10.28修订)
应用题目:http://acm.hdu.edu.cn/showproblem.php?pid=1251
建立字典树,求以……为前缀的单词个数
统计难题
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 3656 Accepted Submission(s): 1295
注意:本题只有一组测试数据,处理到文件结束.
banana band bee absolute acm ba b band abc
2 3 1 0
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
int n,m,ans;
string str;
struct dic_tree //构造字典树,26叉树,根结点为空
{
dic_tree *node[26];//26个结点
int num;//孩子节点数目;
bool terminal;//是否结束;
dic_tree()//构造函数,初始化;
{
for (int i = 0; i < 26; i++)
{
node[i] = NULL;
terminal = 0;
num = 0;
}
}
}*root;//树是通过指针形式来表达;
void build(dic_tree* p, string str, int end)//生成字典树;
{
int ix = 0;
p->num++;
while (ix < end)
{
int c = str[ix]-'a';
cout<<c<<" ";
if (p->node[c]) //如果node[c]存在;
{
p=p->node[c];
if (ix == end-1)
{
p->terminal = 1;
}
++ix;
}
else //node[c]不存在;
{
cout<<"new dic_tree"<<endl;
p->node[c] = new dic_tree ;//在该点生成一个26叉树
p = p->node[c];
if (ix == end-1)
{
p->terminal = 1;
}
++ix;
}
p->num++;//p相对应孩子节点增加;
}
}
int search(dic_tree* p,string str, int end)
{
int ix = 0;
while (ix < end)
{
int c = str[ix] - 'a';
if (p->node[c])
{
p = p->node[c];
if (ix == end-1)
{
p->terminal = 1;
return p->num;
}
ix++;
}
else
return 0;
}
}
int main()
{
root=new dic_tree;
ifstream infile("D:/infile.txt");
while(getline(infile,str))
{
build(root,str,str.size());//生成字典树;
cout<<"build one word"<<endl;
}
//str.clear();
cout<<"Test Word:"<<endl;
while (cin>>str)
{
cout<<search(root,str,str.size())<<endl;;
}
return 0;
}
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{
int i,j,k,len;
string str;char temp[15],temp1[15];
map <string,int> mymap;
while(gets(temp))
{
if(temp[0]=='/n') break;
len=strlen(temp);
if(len==0) break;
for(i=0;i<len;i++)//求出某个字符串的所有前缀,并用MAP存起来
{
for(j=0;j<=i;j++) temp1[j]=temp[j];temp1[j]='/0';
str.assign(temp1);
mymap[str]++;
}
}
while(scanf("%s",&temp)!=EOF)
cout<<mymap[temp]<<endl;//此时直接输出结果即可
return 0;
}
Message Flood
总提交:139 测试通过:27
描述
Well, how do you feel about mobile phone? Your answer would probably be something like that “It’s so convenient and benefits people a lot”. However , if you ask Merlin this question on the New Year’s Eve , he will definitely answer “ What a trouble! I have to keep my fingers moving on the phone the whole night , because I have so many greeting messages to send !” . Yes , Merlin has such a long name list of his friends , and he would like to send a greeting message to each of them . What’s worse , Merlin has another long name list of senders that have sent message to him , and he doesn’t want to send another message to bother them ( Merlin is so polite that he always replies each message he receives immediately ). So , before he begins to send messages , he needs to figure to how many friends are left to be sent . Please write a program to help him.
Here is something that you should note. First , Merlin’s friend list is not ordered , and each name is alphabetic strings and case insensitive . These names are guaranteed to be not duplicated . Second, some senders may send more than one message to Merlin , therefore the sender list may be duplicated . Third , Merlin is known by so many people , that’s why some message senders are even not included in his friend list.
输入
There are multiple test cases . In each case , at the first line there are two numbers n and m ( 1<=n , m<=20000) , which is the number of friends and the number of messages he has received . And then there are n lines of alphabetic strings ( the length of each will be less than 10 ) , indicating the names of Merlin’s friends , one pre line . After that there are m lines of alphabetic string s ,which are the names of message senders .
The input is terminated by n=0.
首先输入两个数m(总朋友数量),n(发送的信息数量),
接着:一系列字符串前m个表示朋友名字
n表示已发送信息的数量
输出:还有几个朋友必须发送信息
输出
For each case , print one integer in one line which indicates the number of left friends he must send .
样例输入
5 3
Inkfish
Henry
Carp
Max
Jericho
Carp
Max
Carp
0
样例输出
3
//搜索+字典树(Trie)
//维基百科关于字典树的介绍
//Trie,又称单词查找树,是一种树形结构,是一种哈希树的变种。
//典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。
//它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,ans;
char str[10];
struct dic_tree//构造字典树,26叉树,根结点为空
{
dic_tree *node[26];//26个结点
bool terminal;//表示该结点位置是否是单词的结束位
dic_tree()//构造函数,初始化终点情况和结点
{
for(int i = 0;i < 26;++i)
{
node[i] = NULL;//初始化空结点,node[0]表示'a'在该单词中
terminal = 0;
}
}
}*root;//树是通过指针形式来表达的
void build(dic_tree *p,char str[],int end)//生成字典树的函数
{
int ix = 0;
while(ix < end)//循环直到读完单词最后一个字母
{
int c = str[ix] - 'a';
if(p->node[c])//如果到node[c]连通
{
p = p->node[c];
if(ix == end - 1)
p->terminal = 1;
++ix;
}
else
{
p->node[c] = new dic_tree; //如果不连通,则在该结点生成一个26叉树
p = p->node[c];
if(ix == end - 1)
p->terminal = 1;
++ix;
}
}
}
void search(dic_tree *p,char str[],int end)
{
int ix = 0;
while(ix < end)
{
int c = str[ix] - 'a';
if(p->node[c])
{
p = p->node[c];
if(ix == end - 1 && p->terminal == 1)
{
--ans;
p->terminal = 0;
return;
}
++ix;
}
else return;
}
}
void release(dic_tree *p)//必须递归释放结点空间
{
for(int i = 0;i < 26; i++)
if(p->node[i])
release(p->node[i]);
delete p;
}
void transcase(char str[])
{
for(int i = 0;i < strlen(str);++i)
{
if(str[i] >= 'A' && str[i] <= 'Z')
str[i] = str[i] - 'A' + 'a';
}
}//转化大小写
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n))
{
if(n == 0) break;
scanf("%d",&m);
root = new dic_tree;
ans = n;
for(int i = 0;i < n;++i)
{
scanf("%s",str);
transcase(str);//转换大小写
build(root,str,strlen(str));//生成字典树
}
for(int i = 0;i < m;++i)
{
scanf("%s",str);
transcase(str);//转换大小写
search(root,str,strlen(str));//搜索字典树
}
printf("%d/n",ans);
release(root);//记住构造树后一定要释放结点空间,否则会内存溢出
}
return 0;
}