日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

字典树-01字典树基础

發(fā)布時(shí)間:2023/12/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字典树-01字典树基础 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

字典樹(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)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。