版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/C_13579/article/details/82189012
字典树模板:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX_S=400005; //字符串的字符总长度
int Trie[MAX_S][26],sum[MAX_S],num;
int n,m;
char s[35];
void insert(char s[]);
bool find(char s[],int rt);
int search(char s[]);
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%s",s);
insert(s);
}
scanf("%d",&m);
for(int i=1;i<=m;++i)
{
scanf("%s",s);
printf("%d\n",search(s));
}
}
void insert(char s[])
{
int u=0,len=strlen(s);
for(int i=0;i<len;++i)
{
int id=s[i]-'a';
if(!Trie[u][id]) Trie[u][id]=++num;
++sum[Trie[u][id]];
u=Trie[u][id];
}
}
bool find(char s[],int rt)
{
bool boo=true;
int len=strlen(s);
for(int i=0;i<len;++i)
{
int x=s[i]-'a';
if(Trie[rt][x]==0){//以rt为头结点的x字母不存在,返回0
boo=false; break;
}
rt=Trie[rt][x];//为查询下个字母做准备
}
return boo;
//查询整个单词时,应该return isw[rt]
}
int search(char s[])
{
int u=0,len=strlen(s);
for(int i=0;i<len;++i)
{
int x=s[i]-'a';
if(!Trie[u][x]) return 0;
u=Trie[u][x];
}//u经过此循环后变成前缀最后一个字母所在位置的后一个位置
return sum[u];//因为前缀后移了一个保存,所以此时的sum[u]就是要求的前缀出现的次数
}
一,HDU-1251-统计难题 :统计前缀字符串个数
Code :
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX_N=400005;
int num;
char ch[15];
int Trie[MAX_N][30],Sum[MAX_N];
void Insert(char ch[]);
int Search(char ch[]);
int main()
{
while(gets(ch)&&ch[0]!='\0'){
Insert(ch);
}
while(gets(ch)){
printf("%d\n",Search(ch));
}
return 0;
}
void Insert(char ch[])
{
int u=0,len=strlen(ch);
for(int i=0;i<len;++i)
{
int t=ch[i]-'a';
if(Trie[u][t]==0) Trie[u][t]=++num;
u=Trie[u][t];
++Sum[u];
}
}
int Search(char ch[])
{
int u=0,len=strlen(ch),res=0;
for(int i=0;i<len;++i)
{
int t=ch[i]-'a';
u=Trie[u][t];
if(!u) break;
}
if(u) res=Sum[u];
return res;
}
二,HDU-2072-单词数 :统计不同单词个数
Code :
#include<iostream>
#include<sstream>
#include<cstring>
using namespace std;
const int MAX_N=50005;
int Trie[MAX_N][30],Sum[MAX_N],num;
string str;
void Insert(string s);
int Find();
int main()
{
ios::sync_with_stdio(false);
while(getline(cin,str)){
if(str=="#") break;
memset(Trie,0,sizeof(Trie));
memset(Sum,0,sizeof(Sum));
num=0;
stringstream sin(str);
while(sin>>str){
Insert(str);
}
cout<<Find()<<endl;
}
return 0;
}
void Insert(string s)
{
int u=0;
for(int i=0;i<s.size();++i)
{
int t=s[i]-'a';
if(Trie[u][t]==0) Trie[u][t]=++num;
u=Trie[u][t];
}
Sum[u]=1;
}
int Find()
{
int res=0;
for(int i=0;i<=num;++i)
res+=Sum[i];
return res;
}
三,POJ-2001-Shortest Prefixes :求唯一标记前缀字符串,只要找到前缀字符串的个数为1即可
Code:
#include<iostream>
using namespace std;
const int MAX_N=1005;
const int MAX_S=20005;
int Trie[MAX_S][30],Sum[MAX_S],num;
string str[MAX_N];
void Insert(string s);
string Search(string s);
int main()
{
ios::sync_with_stdio(false);
int n=0;
while(cin>>str[n]){
Insert(str[n++]);
}
for(int i=0;i<n;++i)
cout<<str[i]<<" "<<Search(str[i])<<endl;
return 0;
}
void Insert(string s)
{
int u=0;
for(int i=0;i<s.size();++i)
{
int t=s[i]-'a';
if(Trie[u][t]==0) Trie[u][t]=++num;
u=Trie[u][t];
++Sum[u];
}
}
string Search(string s)
{
int u=0;
string st="";
for(int i=0;i<s.size();++i)
{
int t=s[i]-'a';
u=Trie[u][t];
st+=s[i];
if(Sum[u]==1) break;
}
return st;
}
四,POJ-3630-Phone List : 判断是否有字符串是另一字符串的前缀,在构造时对字符串的元素做标记,以及对最后一个字符做特殊标记,在判断即可
Code :
#include<iostream>
#include<cstring>
using namespace std;
const int MAX_S=100005;
int n,num,T;
int Trie[MAX_S][15],Sum[MAX_S];
string str;
bool boo;
bool Insert(string s);
int main()
{
ios::sync_with_stdio(false);
cin>>T;
while(T--){
memset(Trie,0,sizeof(Trie));
memset(Sum,0,sizeof(Sum));
boo=true; num=0;
cin>>n;
for(int i=0;i<n;++i)
{
cin>>str;
if(boo&&!Insert(str)) boo=false;
}
if(boo==true) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
bool Insert(string s)
{
bool bo=true;
int u=0;
for(int i=0;i<s.size();++i)
{
int t=s[i]-'0';
if(Trie[u][t]==0) Trie[u][t]=++num;
u=Trie[u][t];
if(Sum[u]==-1){
bo=false; break;
}
if(i!=s.size()-1) Sum[u]=1;
}
if(Sum[u]) bo=false;
Sum[u]=-1;
return bo;
}