关于Trie的一些算法
最近學(xué)習(xí)了一下關(guān)于Trie的一些姿勢,感覺很實(shí)用。
終于不用每次看到字符串判重等操作就只想到hash了
關(guān)于Trie的定義,來自百度百科
在計算機(jī)科學(xué)中,Trie,又稱前綴樹或字典樹,是一種有序樹狀的數(shù)據(jù)結(jié)構(gòu),用于保存關(guān)聯(lián)數(shù)組,其中的鍵通常是字符串。
說的有點(diǎn)高級,我們不要管它,可以看這樣一張圖:
這棵Trie中的單詞共有:his,he,her,me,your
就是從根節(jié)點(diǎn)一直到某個有end(結(jié)尾)標(biāo)記的點(diǎn)
可以發(fā)現(xiàn),Tire其實(shí)就是把一些字符串的公用前綴字符存儲了下來
Tire的實(shí)現(xiàn)更是簡單:
建立一棵Trie,初始時只有一個空的根節(jié)點(diǎn)(編號為0)
每當(dāng)插入或刪除時,如果當(dāng)前字符在之前的操作中已經(jīng)建立,然后直接利用即可,否則新建立一個節(jié)點(diǎn)并讓上一個節(jié)點(diǎn)連上它
當(dāng)一個字符串結(jié)束時,給該節(jié)點(diǎn)做個記號,同時也可存儲些其它的信息
具體的實(shí)現(xiàn)方法也有兩種:鄰接表和鄰接矩陣
在Trie中,顯然用鄰接矩陣是很快的,但空間的開銷可能較大,如果題目說明范圍,那么空間允許的情況下可以使用
鄰接表還是一樣,比較省空間(畢竟要多少開多少)
這里用一道板子題來理解一下:
hihocoder 1366 : 逆序單詞
鄰接矩陣CODE
#include<iostream> #include<string> using namespace std; const int N=50005; struct node {bool end;int next[30]; }trie[N<<4]; string s; int n,ans,cnt; inline bool find(string s) {int now=0,len=s.size();for (register int i=0;i<len;++i){if (trie[now].next[s[i]-'a'+1]) now=trie[now].next[s[i]-'a'+1]; else return 0;if (i==len-1) return trie[now].end;} } inline void insert(string s) {int now=0,len=s.size();for (register int i=0;i<len;++i){if (trie[now].next[s[i]-'a'+1]) now=trie[now].next[s[i]-'a'+1]; else trie[now].next[s[i]-'a'+1]=++cnt,now=cnt;if (i==len-1) trie[now].end=1;} } int main() {register int i;for (cin>>n,i=1;i<=n;++i){cin>>s;string rs(s.rbegin(),s.rend());if (find(rs)) ++ans;insert(s);}cout<<ans;return 0; }鄰接表CODE
#include<iostream> #include<cstring> #include<string> using namespace std; const int N=50005; struct node {bool end;char ch; }trie[N<<4]; struct edge {int to,next; }link[N<<4]; string s; int head[N<<4],n,ans,cnt; inline void add(int x,int y,char z) {link[y].to=y; trie[y].ch=z; link[y].next=head[x]; head[x]=y; } inline bool find(string s) {int now=0,len=s.size();for (register int i=0;i<len;++i){bool flag=0;for (register int j=head[now];j!=-1;j=link[j].next)if (trie[link[j].to].ch==s[i]) { flag=1; now=link[j].to; break; }if (!flag) return 0;if (i==len-1) return trie[now].end;} } inline void insert(string s) {int now=0,len=s.size();for (register int i=0;i<len;++i){bool flag=0;for (register int j=head[now];j!=-1;j=link[j].next)if (trie[link[j].to].ch==s[i]) { flag=1; now=link[j].to; break; }if (!flag) add(now,++cnt,s[i]),now=cnt;if (i==len-1) trie[now].end=1;} } int main() {register int i;memset(link,-1,sizeof(link));memset(head,-1,sizeof(head));for (cin>>n,i=1;i<=n;++i){cin>>s;string rs(s.rbegin(),s.rend());if (find(rs)) ++ans;insert(s);}cout<<ans;return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/cjjsb/p/8835042.html
總結(jié)
以上是生活随笔為你收集整理的关于Trie的一些算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL学习笔记(一)基本查询操作
- 下一篇: lamba List 转 Map