赞
踩
字典树是一种用于实现字符串快速检索的多叉树结构
trie 的每个节点都拥有若干个字符指针,若在插入或检索字符串时扫描到一个字符 c c c
就沿着当前节点的 c c c 字符指针,走向该指针指向的节点
下图即为一个简易版字典树,存储了单词:abc
、bac
、abd
(1) 初始化
一颗空 trie 仅包含一个根节点,该字符的指针均指向空
(2) 插入
当需要插入一个字符串 s s s 时,我们令一个指针 P P P 起初指向根节点。然后依次扫描 s s s 中的每一个字符 c c c
1.若 P P P 的 c c c 字符指针指向一个已经存在的节点 Q Q Q ,则令 P = Q P=Q P=Q
2.若 P P P 的 c c c 字符指针指向空,则新建一个节点 Q Q Q 令 P P P 的 c c c 字符指针指向 Q Q Q ,然后令 P = Q P=Q P=Q
当 S S S 中的字符扫描完毕,在当前节点 P P P 上标记它是一个字符串的末尾
(3) 检索
当需要检索一个字符串 S S S 在 T r i e Trie Trie 中是否存在时,我们令一个指针 P P P 起初指向根节点,然后依次扫描 S S S 中的每个字符 c c c
(1) 若 P P P 的 c c c 字符指针指向空,则说明 S S S 没有被插入到 T r i e Trie Trie 树中,结束检索
(2) 若 P P P 的 c c c 字符指针指向一个已经存在的节点 Q Q Q ,则令 P = Q P=Q P=Q
当 S S S 中的字符扫描完毕
若在当前节点 P P P 被标记为一个 字符串的末尾,则说明 S 在 Trie 树中存在,否则说明 S 没有被插入过
#include<bits/stdc++.h> using namespace std; int trie[ ][ ],tot=1; char str[ ]; bool end[ ]; void put() { //1 int len; //2 int p=1; //3 for(int i=1;i<=len;i++) { int ch=str[i]-'a'; trie[p][ch] //(1)指向空 trie[p][ch]=++tot; //(2)指向已存在 p=trie[p][ch]; } //4 end[p]=true; return; } bool find() { //1 int len; //2 int p=1; //3 for(int i=1;i<=len;i++) { int ch=str[i]-'a'; trie[p][ch] //(1)指向空 return false; //(2)指向已存在 p=trie[p][ch]; } //4 return end[p]; } int main(){ return 0; }
分析:
给定 n n n 个模式串 1,2,…, s 1 s_1 s1, s 2 s_2 s2,…, s n s_n sn 和 q 次询问,每次询问给定一个文本串 t i t_i ti,请回答 1∼ s 1 s_1 s1∼ s n s_n sn 中有多少个字符串 s j s_j sj 满足 t i t_i ti 是 s j s_j sj 的前缀。
那么很明显,这道题主要考的就是我们对于字典树的运用。
除了上文所述的存储方法,还可以运用与其他树形结构相类似的结构体存储:
struct NODE{
int cnt=0;
int son[65];
}node[MAXN];
不过字符还需要转换成一个数字,这里我们就需要用到一个类似于map映射的东西:
int getnumber(char ch)
{
if(ch>='A'&&ch<='Z')
return ch-'A';
if(ch>='a'&&ch<='z')
return ch-'a'+26;
return ch-'0'+52;
}//约等于map映射
插入操作:
void insert(string s)//插入操作,s表示需要插入的字符串
{
now=start;
for(int i=0;i<s.size();i++)
{
num=getnumber(s[i]);
if(node[now].son[num]==0)
node[now].son[num]=++cnt;
node[now].cnt++;
now=node[now].son[num];
}
node[now].cnt++;
return;
}
查询操作:
void find(string s) { now=start; for(int i=0;i<s.size();i++) { num=getnumber(s[i]); if(node[now].son[num]==0) { printf("0\n"); return; } now=node[now].son[num]; } printf("%d\n",node[now].cnt); return; }
整个代码:
#include<bits/stdc++.h> using namespace std; const int MAXN=3e6+5; int num,now,start,cnt; int T,n,q; string s; int getnumber(char ch) { if(ch>='A'&&ch<='Z') return ch-'A'; if(ch>='a'&&ch<='z') return ch-'a'+26; return ch-'0'+52; }//约等于map映射 struct NODE{ int cnt=0; int son[65]; }node[MAXN]; void insert(string s)//插入操作,s表示需要插入的字符串 { now=start; for(int i=0;i<s.size();i++) { num=getnumber(s[i]); if(node[now].son[num]==0) node[now].son[num]=++cnt; node[now].cnt++; now=node[now].son[num]; } node[now].cnt++; return; } void find(string s) { now=start; for(int i=0;i<s.size();i++) { num=getnumber(s[i]); if(node[now].son[num]==0) { printf("0\n"); return; } now=node[now].son[num]; } printf("%d\n",node[now].cnt); return; } int main(){ scanf("%d",&T); while(T--) { scanf("%d%d",&n,&q); while(n--) { cin >> s; insert(s); } while(q--) { cin >> s; find(s); } start=++cnt; } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。