图片来源:百度百科
功能在o(n)的时间插入和查询字符串,n是字符串长度
1.静态
#include<iostream>
using namespace std;
const int N=1e6+10;
int son[N][26],cnt[N],idx;//cnt表示该字符串的数量,son表示字符串的某个字符的下一个节点的位置,其中字符串最后一个字符的son值表示该字符串的编号
int n,m;
string str;
void insert()//插入字符串
{
int p=0;
for(int i=0;i<str.size();i++)
{
if(!son[p][str[i]-'a']) son[p][str[i]-'a']=++idx;//如果在这个字典树中没有就建立一条连接下一个字符的边,并且给这个字符编号
p=son[p][str[i]-'a'];
}
cnt[p]++;//记录字符串数量
}
int query()//返回前缀数量
{
int p=0,res=0;
for(int i=0;i<str.size();i++)
{
if(!son[p][str[i]-'a']) return res;//如果已经没有后面的字符了说明已经查询了所有的字典前缀可以直接返回
p=son[p][str[i]-'a'];
res+=cnt[p];
}
return res;
}
int main()
{
cin>>n>>m;
while(n--)
{
cin>>str;
insert();
}
while(m--)
{
cin>>str;
cout<<query()<<endl;
}
return 0;
}
2.动态(来源:力扣)
class Trie {
private:
vector<Trie*> children;
bool isEnd;
Trie* searchPrefix(string prefix)
{
Trie* node=this;
for(char ch:prefix)
{
ch-='a';
if(node->children[ch]==nullptr)
return nullptr;
node=node->children[ch];
}
return node;
}
public:
Trie() :children(26),isEnd(false){}
void insert(string word) {
Trie *node=this;
for(char ch:word)
{
ch-='a';
if(node->children[ch]==nullptr)
node->children[ch]=new Trie();
node=node->children[ch];
}
node->isEnd=true;
}
bool search(string word) {
Trie* node = this->searchPrefix(word);
return node!=nullptr&&node->isEnd;
}
bool startsWith(string prefix) {
return this->searchPrefix(prefix)!=nullptr;
}
};