1.介绍
一种高效存储和查找字符串集合的数据结构
思想:
空间换时间,利用字符串公共前缀来降低查询的时间开销,从而达到提高效率的目的。
对于庞大的空间开销,我们可以用链表动态来开辟空间,达到空间利用率的最大化。
基本性质:
*根节点不包含字符
*除根节点外,每个节点只包含一个字符
*从根节点到某一节点,路径上经过的字符连接起来,为该结点对应的字符串
图解:
2.结构体表示
#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
char s[N];
struct TireNode{
int count; //统计单词出现的次数
TireNode *next[26];
bool exist; //记录该节点是否构成一个单词
};
//动态分配内存空间
TireNode* CreatTireNode()
{
TireNode *node = new TireNode;
node->count=0;
node->exist=false;
memset(node->next,0,sizeof(node->next));
return node;
}
void insertTire(TireNode *root,char *p)
{
auto node=root;
int i=0;
while(p[i])
{
if(!node->next[p[i]-'a'])
{
node->next[p[i]-'a']=CreatTireNode();//如果该节点不存在,则开辟新的节点储存
}
node=node->next[p[i]-'a'];
i++;
}
if(node->exist) node->count+=1;
else{
node->exist=true;
node->count+=1;
}
}
int serchTire(TireNode* root,char *p)
{
auto node=root;
int id;
int i=0;
while(p[i]!='\0')
{
id=p[i]-'a';
node=node->next[id];
++i;
if(!node) return 0;
}
return node->count;
}
int main()
{
TireNode *root=CreatTireNode();
int n=5;
while(n--)
{
cin>>s;
insertTire(root,s);
}
int sum;
cin>>s;
sum=serchTire(root,s);
cout<<sum;
return 0;
}
3.数组模拟
//插入
void insert(char *str)
{
int p = 0; //类似指针,指向当前节点
for(int i = 0; str[i]; i++)
{
int u = str[i] - 'a'; //将字母转化为数字
if(!son[p][u]) son[p][u] = ++idx;
//该节点不存在,创建节点,其值为下一个节点位置
p = son[p][u]; //使“p指针”指向下一个节点位置
}
cnt[p]++; //结束时的标记,也是记录以此节点结束的字符串个数
}
//查找
int query(char *str)
{
int p = 0;
for(int i = 0; str[i]; i++)
{
int u = str[i] - 'a';
if(!son[p][u]) return 0; //该节点不存在,即该字符串不存在
p = son[p][u];
}
return cnt[p]; //返回字符串出现的次数
}