二维数组存储字典树:
对二维数组的理解:
代表的的是标号为p节点下 子树的节点标号,比如根节点下有 i ,则trie[0][i-‘0’] = 1
刚开始p=0,代表的是从根节点开始,向子树查询。
数组存储的是节点的标号,标号绝对不会重复,是一个数一个数向下递增下去的,如1,2,3,4…
num[p]存储的是以某个节点结尾(以某一字符串为前缀的单词的数量)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int num[maxn];
int trie[maxn][26];
int pos = 1;
//第二维代表该树的子树总子树
void insert(char str[])
{
int p=0;
for(int i=0;str[i];i++)
{
int n = str[i] - 'a';//代表字符
if(trie[p][n]==0) trie[p][n] = pos++;//存储节点的标号
p = trie[p][n];
num[p]++;//标记以该节点为前缀的单词的数量 ,总节点数
}
}
//返回以某个字符前缀的出现的次数
int find(char str[])
{
int p=0;
for(int i=0;str[i];i++)
{
int n=str[i]-'a';
if(trie[p][n]==0) return 0;
p = trie[p][n];
}
return num[p];
}
- 字典树
相关解释:
idx
:节点的标号,每个节点都有一个标号,且trie树中存的都是标号
son[p][u]
:标号为p
的子树中字母ASCII码对应u +'a'
(因为u
是数字,要转化为字母需要加上字符a
)的标号,如果不存在,值为0
cnt[p]
:以节点标号为p
结尾的字符串的个数
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int son[N][26],cnt[N],idx;
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];
}
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];
}
用结构体封装好的trie树
f
i
n
d
(
)
find()
find()方法:返回某个字符串在前缀中的出现次数
i
n
s
e
r
t
(
)
insert()
insert()方法:将字符串插入字典树
struct Trie
{
vector<array<int, 26>> trie;
vector<int> cnt;
int idx = 0;
Trie(int n)
{
trie.resize(n);
cnt.resize(n, 0);
}
void insert(string s)
{
int p = 0;
for(int i = 0; i < (int)s.size(); i++)
{
int x = s[i] - 'a';
if(!trie[p][x]) trie[p][x] = ++idx;
p = trie[p][x];
}
cnt[p++];
}
int find(string s)
{
int p = 0;
for(int i = 0; i < int(s.size()); i++)
{
int x = s[i] - 'a';
if(!trie[p][x]) return 0;
p = trie[p][x];
}
return cnt[p];
}
};