字典树
目录
字典树又称 Trie 树,是一种树形结构。其典型应用是用于统计和排序大量的字符串(但又不仅限与字符串),也可以快速查找前缀。
字典树有三个基本性质:
1.根节点不包含字符,除根节点外的每一个结点都只包含一个字符。
2.从根节点到某一节点,路径上经过的字符连接起来,为该结点对应的字符。
3.每个结点的所有子节点包含的字符都不相同。
上模板:
建树:
//对于字符串比较多的要统计个数的,map被卡的情况下,直接用字典树
//很多题都是要用到节点下标来表示某个字符串
const int maxn =2e6+5; //如果是64MB可以开到2e6+5,尽量开大
int tree[maxn][30]; //tree[i][j]表示节点i的第j个儿子的节点编号
bool ispoint[maxn]; //表示以该节点结尾是一个单词,也可以开成int型
int tot; //总节点数
void insert_(char *str)
{
int len=strlen(str);
int root=0;
for(int i=0;i<len;i++)
{
int id=str[i]-'0';
if(!tree[root][id]) tree[root][id]=++tot;
root=tree[root][id];
}
flagg[root]=true;
}
查询:
bool query(char *str) //查询操作,按具体要求改动
{
int len=strlen(str);
int root=0;
for(int i=0;i<len;i++)
{
int id=str[i]-'0';
if(!tree[root][id]) return false;
root=tree[root][id];
}
return true;
}
用完重新初始化(多组样例尤其重要):
void init() //最后清空,节省时间
{
for(int i=0;i<=tot;i++)
{
flagg[i]=false;
for(int j=0;j<10;j++)
tree[i][j]=0;
}
tot=0; //RE有可能是这里的问题
}
AC模板:求以每个单词为前缀的单词个数:
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+10;
int tree[maxn][30];
bool ispoint[maxn];
int sum[maxn],tot=0;
char s[15];
void insert(char *s)
{
int len=strlen(s);
int root=0; //tot为结点个数
for(int i=0;i<len;++i)
{
int id=s[i]-'a';
if(!tree[root][id]) tree[root][id]= ++tot;
sum[tree[root][id]]++; //每个结点出现的次数
root = tree[root][id];
}
ispoint[root]=true;
}
int query(char *s)
{
int len=strlen(s);
int root = 0;
for(int i=0;i<len;++i)
{
int id=s[i]-'a';
if(!tree[root][id]) return 0;
root=tree[root][id];
}
return sum[root];
}
int main()
{
ios::sync_with_stdio(false);
memset(sum,0,sizeof(sum));
memset(ispoint,false,sizeof(ispoint));
while(cin.getline(s,11))
{
if(strlen(s)==0) break;
insert(s);
}
while(cin>>s)
{
cout<<query(s)<<endl;
}
system("pause");
return 0;
}