字典树的概念
模型是一个多叉树,也叫前缀树,节点与节点之间的存储字符,如果没有储存,说明没有这个字符串,作用主要是处理前缀相同的字符串的冗余情况,也是树型动态规划的基础
字典树的基本模型
这里存储的字符串就是in,te,to
代码部分
这里只是做了插入和查询的简单功能,存储树也是用的二维数组,而且只存储小写字母
1.初始化需要的变量
一个二维数组trie[i][j],值为0时说明字符没有初始化,i代表当前的节点编号,j代表目标节点字符编号
一个一维数组color[i],i代表节点编号,color的值为0或1,1代表是叶子节点,因为当我们查询一个字符串时,只有到达叶子节点才能说明之前存储了这个字符串
const int MAX_NODE=1000000; //总结点最大数量
const int CHARSET=26; //字典树且都为小写字母
int trie[MAX_NODE][CHARSET]={
0}; //0表示该节点没被添加过
int color[MAX_NODE]={
0}; //对每个节点进行标记 1为叶子节点
int k=1; //记录节点个数以及标记当前节点的
2.插入功能
向字典树中插入一个字符串,当前字符不存在时,我们需要将字符插入,并改变trie节点的值为当前节点的数量加一,在最后一个节点的位置将color设置为1
void insert(string w) //增加节点
{
int len=w.length();
int p=0;
for(int i=0;i<len;i++)
{
int c=w[i]-'a'; //字母转换成数字
if(!trie[p][c]) //如果当前节点没有到该节点的路径就添加
{
trie[p][c]=k;
++k;
}
p=trie[p][c]; //遍历下一个
}
color[p]=1; //标记叶子节点
}
3.查询功能
逐个字符进行查询,如果当前要查询的字符,所在节点值为0说明之前没有插入该字符串直接返回false,最后整个要查询的字符串判断完成后,还需要判断到达的点是否为叶子节点
int search(string s) //查找节点
{
int len=s.length();
int p=0;
for(int i=0;i<len;i++)
{
int c=s[i]-'a';
if(!trie[p][c]) return false;
p=trie[p][c];
}
return color[p]==1; //能找到该节点且该节点必须是叶子节点
}
完整代码
#include <bits/stdc++.h>
using namespace std;
const int MAX_NODE=1000000; //总结点最大数量
const int CHARSET=26; //字典树且都为小写字母
int trie[MAX_NODE][CHARSET]={
0}; //0表示该节点没被添加过
int color[MAX_NODE]={
0}; //对每个节点进行标记 1为叶子节点
int k=1; //记录节点个数以及标记当前节点的
void insert(string w) //增加节点
{
int len=w.length();
int p=0;
for(int i=0;i<len;i++)
{
int c=w[i]-'a'; //字母转换成数字
if(!trie[p][c]) //如果当前节点没有到该节点的路径就添加
{
trie[p][c]=k;
++k;
}
p=trie[p][c]; //遍历下一个
}
color[p]=1; //标记叶子节点
}
int search(string s) //查找节点
{
int len=s.length();
int p=0;
for(int i=0;i<len;i++)
{
int c=s[i]-'a';
if(!trie[p][c]) return false;
p=trie[p][c];
}
return color[p]==1; //能找到该节点且该节点必须是叶子节点
}
int main (void)
{
int strcnt,searchcnt; //插入字符串数量和查询字符串的数量
cout<<"输入需要插入的字符串数量:";
cin>>strcnt;
vector<string> str(strcnt); //插入的字符串数组
cout<<"下面请输入"<<strcnt<<"个字符串:\n";
for(int i=0;i<strcnt;i++)
{
cin>>str[i];
insert(str[i]);
}
while(1)
{
string tmp;
cout<<"输入需要查询的小写字母组成的字符串(输入Q退出)\n";
cin>>tmp;
if(tmp=="Q")
return 0;
else
{
if(search(tmp))
cout<<"YES\n";
else
cout<<"NO\n";
}
}
return 0;
}
运行效果
总结
个人感觉字典树(前缀树)是处理字符串算法题的一种记忆化的方法,将重复处理字符串相同的前缀的步骤省去