字典树-01字典树基础
字典樹(shù)-01字典樹(shù)
什么是字典樹(shù)?
字典樹(shù),又叫前綴樹(shù),Trie樹(shù),通常被用作字符串匹配。
它的實(shí)現(xiàn)原理是什么?
先建立一顆樹(shù),對(duì)于這棵樹(shù)上每個(gè)節(jié)點(diǎn)i與其后繼節(jié)點(diǎn)間的連線,都有存入一個(gè)字符。
對(duì)于存圖時(shí),從0節(jié)點(diǎn)開(kāi)始遍歷,找到其與其他出現(xiàn)過(guò)的字符第前綴不同的地方,新增節(jié)點(diǎn)。代碼如下:
int p = 0, k = 0; for(int i = 0; i < str.length(); i++){int t = str[i] - 'a';if(!st[p][t]) st[p][t] = k++;p = st[p][t]; }以上代碼,p為當(dāng)前節(jié)點(diǎn)編號(hào),k為新增節(jié)點(diǎn)編號(hào)。當(dāng)查找到有不同的字符,由p指向t,新增節(jié)點(diǎn)k,k自增1作為下一節(jié)點(diǎn),并將p更新到新增節(jié)點(diǎn),以便后續(xù)字符的添加。
對(duì)于查詢,則是相同的思路。代碼如下:
int p = 0; for(int i = 0; i < s.length(); i++){if(!st[p][s[i] - 'a'])return -1;p=st[p][s[i] - 'a']; } return 1;若出現(xiàn)的字符不存在樹(shù)中,直接返回-1,代表查詢失敗。全部查詢結(jié)束,代表查詢成功,返回1.
模板樣例:
輸入n,m,分別為字符串?dāng)?shù)量與查詢字符串?dāng)?shù)量,接下來(lái)m+n行字符串
輸出m行,若存在則輸出"存在",否則輸出"不存在".
輸入樣例
5 3 abccc jcjcj abaca kacbd kacbdaa abc aba abd輸出樣例
存在 存在 不存在代碼
#include<iostream> #include<algorithm> #include<stdio.h> #include<string> #include<string.h>using namespace std;int st[1005][30]; string str; int k = 1;void sett(string str) {int p = 0;for (int i = 0; i < str.length(); i++) {int t = str[i] - 'a' + 1;if (!st[p][t]) st[p][t] = k++;p = st[p][t];} }bool seac() {cin >> str;int p = 0;for (int i = 0; i < str.length(); i++) {int t = str[i] - 'a' + 1;if (!st[p][t]) return false;p = st[p][t];}return true; }int main() {int n, m;cin >> n >> m;while (n--) {cin >> str;sett(str);}while (m--) {if (seac())cout << "存在\n";else cout << "不存在\n";}return 0; }什么是01字典樹(shù)?
01字典樹(shù)主要解決異或最值問(wèn)題。
算法原理
同trie一樣,將其中的字符轉(zhuǎn)為0或1即可。
存圖
int p = 0; for(int i = 32; i >= 0; i--){int t = (x >> i) & 1;if(!st[p][t]) st[p][t]=k++;p = st[p][t]; } val[p]=x;存圖時(shí),從為高位,每個(gè)鏈都有32層,是一個(gè)完全二叉樹(shù),以方便查詢時(shí)對(duì)異或查找的便捷。
注:雖然圖為32層,但是加入的節(jié)點(diǎn)(可查詢節(jié)點(diǎn)的數(shù)量)只有你輸入數(shù)字二進(jìn)制為1的數(shù)量。因此不必?fù)?dān)心查詢過(guò)慢的問(wèn)題。
查詢
int p = 0; for(int i = 32; i >= 0; i--){int t = (x >> i) & 1;if(!st[p][t]) p = st[p][t];//此處是根據(jù)計(jì)算異或的最大或最小值,按照貪心方法計(jì)算,若最大,優(yōu)先找不同的點(diǎn),反之則反else p = st[p][t ^ 1]; } return val[p];代碼
#include<iostream> #include<algorithm> #include<stdio.h> #include<string> #include<string.h> typedef long long ll;using namespace std;int k = 1; int st[10005][2]; int val[10005];void insert(int x){int p = 0;for(int i = 32; i >= 0; i--){int t = (x >> i) & 1;if(!st[p][t]) st[p][t]=k++;p = st[p][t];}val[p]=x; }int seacher(int x){int p = 0;for(int i = 32; i >= 0; i--){int t = (x >> i) & 1;if(st[p][t ^ 1]) p = st[p][t ^ 1];else p = st[p][t];}return val[p]; }int main() {int n;cin>>n;while(n--){int a;cin>>a;insert(a);}int num;cin>>num;cout<<(seacher(num)^num)<<endl;return 0; }總結(jié)
以上是生活随笔為你收集整理的字典树-01字典树基础的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 停电了空调没关怎么办
- 下一篇: 可持久化-可持久化字典树