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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Trie:hdu 4825、1251、1247、Poj 3764

發布時間:2023/12/4 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Trie:hdu 4825、1251、1247、Poj 3764 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

hdu 4825鏈接

題目意思很簡單,就是要求最大異或值的數。
我們可以從二進制的最高位開始選擇,不斷的排除一些數。我們先假設存在某些數字的二進制數是與當前查找的數不一樣的,我們進入這一部分數進行查找,以此重復,不斷排除一部分數,最后找到最佳的數。
如果在查找的過程中某一位不存在不相同的數,我們就只能從相同的數中查找了。
總結一句就是優先查找不同的。

#include<iostream> #include<cstring> #include<cstdio> using namespace std; typedef unsigned int ui;//unsigned int防止出現爆int. const int N1 = 4e6 + 10; ui trie[N1][2], tot, flag[N1]; void build_trie(ui x) {//建立字01字典樹的過程。int root = 0;for(int i = 31; i >= 0; i--) {題意不超過2^32,從32位開始,其實也可以30,但是不要超過31,如果用int.int u = x >> i & 1;if(!trie[root][u]) trie[root][u] = ++tot;root = trie[root][u];}flag[root] = x;//這個節點標記為這個數的值。 } ui find_max(ui x) {//找到與之匹配的異化值最大的數。int root = 0;for(int i = 31; i >= 0; i--) {int u = x >> i & 1;//取出這一位的二進制數。if(trie[root][!u])//優先進入與之不同的二進制數位。root = trie[root][!u];else root = trie[root][u];}return flag[root];//返回查找的最優答案。 } int main() { // freopen("D:\\Code\\ce.txt", "r", stdin);ui t, a, n, m;scanf("%u", &t);for(int k = 1; k <= t; k++) {printf("Case #%d:\n", k);tot = 0;memset(trie, 0, sizeof trie);//多組讀入,注意清零。scanf("%u %u", &n, &m);for(int i = 0; i < n; i++) {scanf("%u", &a);build_trie(a);}for(int i = 0; i < m; i++) {scanf("%u", &a);printf("%u\n", find_max(a));}}return 0; }

hdu 1251鏈接

這題應該比上題還簡單,直接上代碼了。

#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int N = 3e6 + 10; int trie[N][26], flag[N], tot; char s[20]; void build_trie() {int root = 0, n = strlen(s);for(int i = 0; i < n; i++) {int u = s[i] - 'a';if(!trie[root][u]) trie[root][u] = ++tot;root = trie[root][u];flag[root]++;//單詞經過的節點,加一。} } int find_sum() {int root = 0, n = strlen(s);for(int i = 0; i < n; i++) {int u = s[i] - 'a';if(!trie[root][u]) return 0;//出現一個字母在字典中不匹配,立即返回查找不到。root = trie[root][u];}return flag[root];//返回這個節點有多少單詞經過 } int main() { // freopen("D:\\Code\\ce.txt", "r", stdin);while(gets(s)) {if(s[0] == 0)break;build_trie();}while(gets(s))printf("%d\n", find_sum());return 0; }

hdu 1247鏈接

這題應該是比上兩題更難一點,具體看代碼詳解吧。

#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N1 = 5e6 + 10, N2 = 5e4 + 10; int trie[N1][26], is_word[N1], tot; string str[N2]; void build_trie(string s) {//建字典樹。int root = 0, n = s.size();for(int i = 0; i < n; i++) {int u = s[i] - 'a';if(!trie[root][u]) trie[root][u] = ++tot;root = trie[root][u];}is_word[root] = 1;//標記這個節點有單詞。 } bool judge_tail(string s, int pos) {//判斷后綴是否是一個單詞,pos是后綴的起始位置。int root = 0, n = s.size();for(int i = pos; i < n; i++) {int u = s[i] - 'a';if(!trie[root][u]) return false;root = trie[root][u];if(is_word[root] && i == n - 1)//整個需要判斷的后綴是否是一個單詞。return true;}return false; } bool judge_front(string s) {//這里判斷單詞的前綴是否是一個單詞。int root = 0, n = s.size();for(int i = 0; i < n; i++) {int u = s[i] - 'a';if(!trie[root][u]) return false;//有一個字母沒有查找到,返回失敗。root = trie[root][u];if(is_word[root] && judge_tail(s, i + 1))//前綴是一個單詞,接下來就是判斷后綴是否是一個單詞。return true;}return false; } int main() { // freopen("D:\\Code\\ce.txt", "r", stdin);int n = 0;while(cin >> str[n])build_trie(str[n++]);for(int i = 0; i < n; i++)if(judge_front(str[i]))cout << str[i] << endl; return 0; }

Poj 3764鏈接

這題應該是這幾題里面最難的題了,但是卻又跟第一題有點類似。

#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; const int N1 = 2e5 + 10, N2 = 4e6 + 10; int trie[N2][2], tot, cnt, n, head[N1], a[N1]; struct Edge {//鏈式向前星。int to, next, value; }edge[N1]; void add(int x, int y, int value) {//存圖的過程edge[cnt].to = y;edge[cnt].value = value;edge[cnt].next = head[x];head[x] = cnt++; } void dfs(int u, int fa, int sum) {//通過dfs得到每個節點到根節點的異或值。a[u] = sum;for(int i = head[u]; i; i = edge[i].next) {if(edge[i].to != fa) dfs(edge[i].to, u, sum ^ edge[i].value);} } void build_trie(int x) {//建立字典樹。int root = 0;for(int i = 30; i >= 0; i--) {int u = x >> i & 1;if(!trie[root][u]) trie[root][u] = ++tot;root = trie[root][u];} } int find_max(int x) {//查找最大值。int root = 0, ans = 0;for(int i = 30; i >= 0; i--) {int u = x >> i & 1;if(trie[root][!u]) {ans += (1 << i);//如果走這里的話,我們可以得到答案的這一位是1,或者我們可以像第一題一樣現在建立字典樹的時候記錄下節點的值然后在返回這個最大值,最后再和當前查找的異或。root = trie[root][!u];}else root = trie[root][u];}return ans; } int main() {while(scanf("%d", &n) != EOF) {tot = 0, cnt = 1;memset(trie, 0, sizeof trie);memset(head, 0, sizeof head); //多組輸入, 清零。for(int i = 1; i < n; i++) {int x, y, v;scanf("%d %d %d", &x, &y, &v);add(x, y, v);add(y, x, v);}dfs(0, 0, 0);for(int i = 0; i < n; i++)//得到異或值后,開始建字典樹。build_trie(a[i]);int ans = 0;for(int i = 0; i < n; i++)ans = max(ans, find_max(a[i]));printf("%d\n", ans); }return 0; }

總結

以上是生活随笔為你收集整理的Trie:hdu 4825、1251、1247、Poj 3764的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。