标签:set get root out problem 插入 位置 fine pac
Trie树
概要:
字典树算法主要是对字符串进行处理,最后形成形如下图的trie树
字典树主要用来查询前缀出现次数,字符串以前缀代表,查找单词,对某个单词的操作和询问
在形成字典树的时候遵循的原则:
1.根节点0不标记如图所示,单词是否出现以单词的下个节点来作为判断如果上所示的‘$‘,实际上也就是每个字符都是存在边上的
2.单词的插入,首先单词cat进行插入,然后下一个下一个,若单词的前缀相同的时候用的是同一个节点的分支
3.一个节点最多就26个分支所以模板代码的数组开的[][26]
trie树模板:
进行单词的插入:
void Insert(char s[],int rt) { for(int i=0;s[i]!=‘\0‘;++i) { int id=s[i]-‘a‘; if(!trie[rt][id])//现在插入的之前未出现过 trie[rt][id]=++tot; rt=trie[rt][id]; // ++sum[rt]; } // vis[rt]=1; }
单词是否出现过-注意如果不是查询前缀还要做的一步就是查询这个节点结束的位置在vis中是不是一个单词的结束点
int Find(char s[],int rt) { for(int i=0;s[i]!=‘\0‘;++i) { int id=s[i]-‘a‘; if(trie[rt]id]==0) return 0;//无此节点 rt=trie[rt][id]; } return 1; }
查询前缀出现的次数
int SearchNumber(char s[],int rt)//寻找前缀数 { for(int i=0;s[i]!=‘\0‘;++i) { int id=s[i]-‘a‘; if(!trie[rt][id]) return 0; root=trie[rt][id]; } return sum[rr];//找到前缀 }
查询能代表单词的前缀
void ask(char s[],int rt)//用前缀来代表整个单词 { for(int i=0;s[i]!=‘\0‘;++i) { if(sum[rt]==1) break; int id=s[i]-‘a‘; printf("%c",s[i]); rt=trie[rt][id]; } }
const int maxn=1e6+10; int trie[maxn][27]; int tot=1,n; //bool vis[maxn];//检查是否为单词 int sum[maxn];
注意:单词的前缀和单词的结束节点都是在trie[rt][id]存好后的下一个节点,具体看上面的图分析
应用:
1.查询能代表单词的前缀
POJ2001-Shortest Prefixes
#include <iostream> #include<algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> #include<map> #include<set> #include<sstream> #define INF 0x3f3f3f3f #define DOF 0x7f7f7f7f #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); typedef long long ll; using namespace std; const int maxn=1e6+10; int trie[maxn][27]; int tot=1,n; //bool vis[maxn];//检查是否为单词 char s[1010][35]; int sum[maxn]; void Insert(char s[],int rt) { for(int i=0;s[i]!=‘\0‘;++i) { int id=s[i]-‘a‘; if(!trie[rt][id])//现在插入的之前未出现过 trie[rt][id]=++tot; rt=trie[rt][id]; // ++sum[rt]; } // vis[rt]=1; } int Find(char s[],int rt) { for(int i=0;s[i]!=‘\0‘;++i) { int id=s[i]-‘a‘; if(trie[rt]id]==0) return 0;//无此节点 rt=trie[rt][id]; } return 1; } int SearchNumber(char s[],int rt)//寻找前缀数 { for(int i=0;s[i]!=‘\0‘;++i) { int id=s[i]-‘a‘; if(!trie[rt][id]) return 0; root=trie[rt][id]; } return sum[rr];//找到前缀 } void ask(char s[],int rt)//用前缀来代表整个单词 { for(int i=0;s[i]!=‘\0‘;++i) { if(sum[rt]==1) break; int id=s[i]-‘a‘; printf("%c",s[i]); rt=trie[rt][id]; } } int main() { // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); int n=0; while(scanf("%s",s[++n])!=EOF) Insert(s[n],0); for(int i=1;i<=n;++i) { printf("%s ",s[i]); ask(s[i],0); printf("\n"); } // system("pause"); }
附上学习时候看的博客:https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html
标签:set get root out problem 插入 位置 fine pac
原文地址:https://www.cnblogs.com/waryan/p/12620976.html