字典树中根到每个结点对应原串集合的一个前缀,这个前缀由路径上所有转移边对应的字母构成。我们可以对每个结点维护一些需要的信息,这样即可以去做很多事情。

#10049. 「一本通 2.3 例 1」Phone List

#include <bits/stdc++.h>
using namespace std; namespace Trie {
struct Node {
Node *ch[];
int val;
Node* clear() {
for(int i=;i<;i++) ch[i]=NULL;
val=;
return this;
}
}; Node *root;
Node pool[];
int ind=;
Node* newnode() {
return pool[ind++].clear();
} void clear() {
ind=;
root=newnode();
}
void insert(string s) {
Node *pos=root;
for(int i=;i<s.length();i++) {
if(pos->ch[s[i]]==NULL) pos->ch[s[i]]=newnode();
pos->val++;
pos=pos->ch[s[i]];
}
}
int query(string s) {
Node *pos=root;
for(int i=;i<s.length();i++) {
if(pos->ch[s[i]]==NULL) return ;
pos=pos->ch[s[i]];
}
return pos->val;
} string str[]; void solve() {
int n;
cin>>n;
clear();
for(int i=;i<=n;i++) {
cin>>str[i];
for(int j=;j<str[i].length();j++) str[i][j] -= '';
insert(str[i]);
}
int flag=;
for(int i=;i<=n;i++) {
if(query(str[i])) {
flag=;
break;
}
}
if(flag) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
} int main() {
int t;
ios::sync_with_stdio(false);
cin>>t;
while(t--) Trie::solve();
return ;
}

#10050. 「一本通 2.3 例 2」The XOR Largest Pair

0-1 Trie通常用于异或相关的问题,思路是记录所有01串后,我们找最大异或和的时候可以从高位到低位贪心,此时Trie发挥的作用就是在当前前缀已经选择的情况下,能使得正在考虑位异或为1的后缀是否存在。

#include <bits/stdc++.h>
using namespace std; namespace Trie {
struct Node {
Node *ch[];
Node *clear() {
ch[] = ch[] = ;
return this; // Don't forget this
}
};
Node *root;
Node pool[];
int ind;
Node *newnode() { return pool[ind++].clear(); }
void insert(int x) {
Node *pos = root;
for (int i = ; i >= ; --i) {
int b = (x / ( << i)) & ;
if (pos->ch[b] == NULL)
pos->ch[b] = newnode();
pos = pos->ch[b];
}
}
int query(int x) {
Node *pos = root;
int ans = ;
for (int i = ; i >= && pos != NULL; --i) {
int b = (x / ( << i)) & ;
if (pos->ch[b ^ ] != NULL)
pos = pos->ch[b ^ ], ans += ( << i);
else
pos = pos->ch[b];
}
return ans;
}
int a[];
void solve() {
int n, ans = ;
cin >> n;
root = newnode(); // Don't forget this
for (int i = ; i <= n; i++) cin >> a[i], insert(a[i]);
for (int i = ; i <= n; i++) ans = max(ans, query(a[i]));
cout << ans << endl;
}
} // namespace Trie int main() {
ios::sync_with_stdio(false);
Trie::solve();
}

#10051. 「一本通 2.3 例 3」Nikitosh 和异或

看到这个算式我们很容易想到前缀和转化。问题转化为求s[r1]^s[l1-1] + s[r2]^s[l2-1]最大。

由于要r1<l2,所以可考虑去处理出一个前缀max和一个后缀max,然后枚举分界点。那么答案就是

Max{pre[i]+suf[i+1]}

#include <bits/stdc++.h>
using namespace std; namespace Trie {
struct Node {
Node *ch[];
Node *clear() {
ch[] = ch[] = ;
return this; // Don't forget this
}
};
Node *root;
Node pool[];
int ind;
Node *newnode() { return pool[ind++].clear(); }
void insert(int x) {
Node *pos = root;
for (int i = ; i >= ; --i) {
int b = (x / ( << i)) & ;
if (pos->ch[b] == NULL)
pos->ch[b] = newnode();
pos = pos->ch[b];
}
}
int query(int x) {
Node *pos = root;
int ans = ;
for (int i = ; i >= && pos != NULL; --i) {
int b = (x / ( << i)) & ;
if (pos->ch[b ^ ] != NULL)
pos = pos->ch[b ^ ], ans += ( << i);
else
pos = pos->ch[b];
}
return ans;
}
int a[], pre[], suf[];
void solve() {
int n, ans = ;
cin >> n;
root = newnode(); // Don't forget this
for (int i = ; i <= n; i++) cin >> a[i], insert(a[i]), pre[i] = max(pre[i - ], query(a[i]));
ind = ;
root = newnode();
reverse(a + , a + n + );
for (int i = ; i <= n; i++) insert(a[i]), suf[i] = max(suf[i - ], query(a[i]));
reverse(suf + , suf + n + );
for (int i = ; i < n; i++) ans = max(ans, pre[i] + suf[i + ]);
cout << ans << endl;
}
} // namespace Trie int main() {
ios::sync_with_stdio(false);
Trie::solve();
}

#10052. 「一本通 2.3 练习 1」Immediate Decodability

和前面那题一样

#include <bits/stdc++.h>
using namespace std; namespace Trie {
struct Node {
Node *ch[];
int val;
Node *clear() {
for (int i = ; i < ; i++) ch[i] = NULL;
val = ;
return this;
}
}; Node *root;
Node pool[];
int ind = ;
Node *newnode() { return pool[ind++].clear(); } void clear() {
ind = ;
root = newnode();
}
void insert(string s) {
Node *pos = root;
for (int i = ; i < s.length(); i++) {
if (pos->ch[s[i]] == NULL)
pos->ch[s[i]] = newnode();
pos->val++;
pos = pos->ch[s[i]];
}
}
int query(string s) {
Node *pos = root;
for (int i = ; i < s.length(); i++) {
if (pos->ch[s[i]] == NULL)
return ;
pos = pos->ch[s[i]];
}
return pos->val;
} string str[]; bool solve(int t) {
clear();
int n = ;
while (cin >> str[++n]) {
if (str[n][] == '')
break;
for (int j = ; j < str[n].length(); j++) str[n][j] -= '';
insert(str[n]);
}
--n;
if (n <= )
return false;
int flag = ;
for (int i = ; i <= n; i++) {
if (query(str[i])) {
flag = ;
break;
}
}
if (flag)
cout << "Set " << t << " is not immediately decodable" << endl;
else
cout << "Set " << t << " is immediately decodable" << endl;
return true;
}
} // namespace Trie int main() {
int t = ;
ios::sync_with_stdio(false);
while (Trie::solve(++t))
;
return ;
}

#10053. 「一本通 2.3 练习 2」L 语言

我们记录u[i]表示文章的每一个前缀s[1..i]是否可被理解。做一个类似dp的处理即可。

刚开始忘记传引用T了半天……

#include <bits/stdc++.h>
using namespace std; char buf[]; void readstr(string &tar) {
scanf("%s", buf);
tar = buf;
} int __cnt = ; namespace Trie {
struct Node {
Node *ch[];
int val;
Node *clear() {
for (int i = ; i < ; i++) ch[i] = NULL;
val = ;
return this;
}
}; Node *root;
Node pool[];
int u[];
int ind = , ans = ;
Node *newnode() { return pool[ind++].clear(); } void clear() {
ind = ;
root = newnode();
}
void insert(string &s) {
Node *pos = root;
for (int i = ; i < s.length(); i++) {
if (pos->ch[s[i]] == NULL)
pos->ch[s[i]] = newnode();
pos = pos->ch[s[i]];
}
pos->val++;
}
void query(string &s, int start) {
Node *pos = root;
int len = s.length();
for (int i = start; i < len; i++) {
__cnt++;
if (pos->ch[s[i]] == NULL)
return;
pos = pos->ch[s[i]];
if (pos->val)
u[i + ] = , ans = max(ans, i + );
}
} string str[];
string art; void solve() {
int n, m;
scanf("%d%d", &n, &m);
clear();
for (int i = ; i <= n; i++) {
readstr(str[i]);
for (int j = ; j < str[i].length(); j++) str[i][j] -= 'a';
insert(str[i]);
}
for (int i = ; i <= m; i++) {
ans = ;
memset(u, , sizeof u);
readstr(art);
int len = art.length();
for (int j = ; j < len; j++) art[j] -= 'a';
u[] = ;
for (int j = ; j < len; j++) {
if (u[j] == )
continue;
query(art, j);
}
cout << ans << endl;
}
}
} // namespace Trie int main() {
int t;
ios::sync_with_stdio(false);
Trie::solve();
// cout<<__cnt<<endl;
return ;
}

#10054. 「一本通 2.3 练习 3」Secret Message 秘密信息

对信息建Trie,仍然是在每个串的结束点上打标记。结果就等于把密码串丢上去跑,跑的路径上的标记和,加上最终停在的结点(如果整个密码串都成功匹配)的子树的标记和。前一个直接记录,后一个用树上前缀和预处理一下即可。

#include <bits/stdc++.h>
using namespace std; namespace Trie {
struct Node {
Node *ch[];
int val, sum;
Node *clear() {
for (int i = ; i < ; i++) ch[i] = NULL;
val = sum = ;
return this;
}
}; Node *root;
Node pool[];
int ind = ;
Node *newnode() { return pool[ind++].clear(); } void clear() {
ind = ;
root = newnode();
}
void insert(int len) {
Node *pos = root;
for (int i = ; i < len; i++) {
int si;
cin >> si;
if (pos->ch[si] == NULL)
pos->ch[si] = newnode();
pos = pos->ch[si];
}
pos->val++;
}
void dfs(Node *p) {
if (p == NULL)
return;
dfs(p->ch[]);
dfs(p->ch[]);
p->sum = p->val;
if (p->ch[])
p->sum += p->ch[]->sum;
if (p->ch[])
p->sum += p->ch[]->sum;
}
int query(int len) {
Node *pos = root;
int ans = ;
for (int i = ; i < len; i++) {
int si;
cin >> si;
ans += pos->val;
if (pos->ch[si] == NULL) {
for (int j = ; j <= len - i - ; j++) cin >> si;
return ans;
}
pos = pos->ch[si];
}
return ans + pos->sum;
} string str[]; void solve() {
int m, n;
cin >> m >> n;
clear();
for (int i = ; i <= m; i++) {
int len;
cin >> len;
insert(len);
}
dfs(root);
for (int i = ; i <= n; i++) {
int len;
cin >> len;
cout << query(len) << endl;
}
}
} // namespace Trie int main() {
int t;
ios::sync_with_stdio(false);
Trie::solve();
return ;
}

#10056. 「一本通 2.3 练习 5」The XOR-longest Path

树上前缀异或和以后直接转化为两点最大异或和。其实用欧拉序也可以。

#include <bits/stdc++.h>
using namespace std; namespace Trie {
struct Node {
Node *ch[];
Node* clear() {
ch[]=ch[]=;
return this; // Don't forget this
}
};
Node *root;
Node pool[];
int ind;
Node* newnode() {
return pool[ind++].clear();
}
void insert(int x) {
Node *pos = root;
for(int i=;i>=;--i) {
int b=(x/(<<i))&;
if(pos->ch[b]==NULL) pos->ch[b]=newnode();
pos=pos->ch[b];
}
}
int query(int x) {
Node *pos = root;
int ans = ;
for(int i=;i>= && pos!=NULL;--i) {
int b=(x/(<<i))&;
if(pos->ch[b^]!=NULL)
pos=pos->ch[b^], ans+=(<<i);
else pos=pos->ch[b];
}
return ans;
}
int a[];
void solve(int n) {
int ans=;
root=newnode(); // Don't forget this
for(int i=;i<=n;i++) insert(a[i]);
for(int i=;i<=n;i++) ans=max(ans,query(a[i]));
cout<<ans<<endl;
}
}
int n,vis[];
vector<pair<int,int> > g[]; void dfs(int p) {
vis[p]=;
for(int i=;i<g[p].size();i++) {
int q=g[p][i].first;
if(vis[q]==) {
Trie::a[q]=Trie::a[p] ^ g[p][i].second;
dfs(q);
}
}
} int main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=;i<n;i++) {
int u,v,w;
cin>>u>>v>>w;
g[u].push_back(make_pair(v,w));
g[v].push_back(make_pair(u,w));
}
dfs();
Trie::solve(n);
}

[一本通学习笔记] 字典树与 0-1 Trie的更多相关文章

  1. 《python基础教程(第二版)》学习笔记 字典(第4章)

    <python基础教程(第二版)>学习笔记 字典(第4章)创建字典:d={'key1':'value1','key2':'value2'}lst=[('key1','value1'),(' ...

  2. 一起学ASP.NET Core 2.0学习笔记(二): ef core2.0 及mysql provider 、Fluent API相关配置及迁移

    不得不说微软的技术迭代还是很快的,上了微软的船就得跟着她走下去,前文一起学ASP.NET Core 2.0学习笔记(一): CentOS下 .net core2 sdk nginx.superviso ...

  3. 算法笔记--字典树(trie 树)&& ac自动机 && 可持久化trie

    字典树 简介:字典树,又称单词查找树,Trie树,是一种树形结构,是哈希树的变种. 优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较. 性质:根节点不包含字符,除根节点外每一个 ...

  4. [一本通学习笔记] AC自动机

    AC自动机可以看作是在Trie树上建立了fail指针,在这里可以看作fail链.如果u的fail链指向v,那么v的对应串一定是u对应串在所给定字符串集合的后缀集合中的最长的后缀. 我们考虑一下如何实现 ...

  5. 学习笔记-动态树Link-Cut-Tree

    --少年你有梦想吗? --少年你听说过安利吗? 安利一个集训队讲解:http://wenku.baidu.com/view/75906f160b4e767f5acfcedb 关于动态树问题,有多种方法 ...

  6. NVIDIA DIGITS 学习笔记(NVIDIA DIGITS-2.0 + Ubuntu 14.04 + CUDA 7.0 + cuDNN 7.0 + Caffe 0.13.0)

    转自:http://blog.csdn.net/enjoyyl/article/details/47397505?from=timeline&isappinstalled=0#10006-we ...

  7. Python学习笔记(字典)

    今天学习一个python中的基本类型--字典(dictionary) 字典这种数据结构有点像我们平常用的通讯录,有一个名字和这个名字对应的信息.在字典中,名字叫做“键”,对应的内容信息叫做“值”.字典 ...

  8. [一本通学习笔记] 最近公共祖先LCA

    本节内容过于暴力没什么好说的.借着这个专题改掉写倍增的陋习,虽然写链剖代码长了点不过常数小还是很香. 10130. 「一本通 4.4 例 1」点的距离 #include <bits/stdc++ ...

  9. [一本通学习笔记] RMQ专题

    傻傻地敲了好多遍ST表. 10119. 「一本通 4.2 例 1」数列区间最大值 #include <bits/stdc++.h> using namespace std; const i ...

随机推荐

  1. MATLAB实例:二元高斯分布图

    MATLAB实例:二元高斯分布图 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 1. MATLAB程序 %% demo Multivariate No ...

  2. css常用样式背景background如何使用

    css背景background属性常用于定义HTML的背景,background简写属性作用是将背景属性设置在一个声明中,background背景属性常见为以下这些:.background-color ...

  3. 纪中23日c组T3 2161. 【2017.7.11普及】围攻 斐波那契数列

    2161. 围攻 (File IO): input:siege.in output:siege.out 时间限制: 1000 ms  空间限制: 262144 KB  具体限制   Goto Prob ...

  4. JavaSE学习笔记(4)---抽象类和接口

    JavaSE学习笔记(4)---抽象类和接口 抽象方法和抽象类 ·抽象方法 使用abstract修饰的方法,没有方法体,只有声明.定义的是一种"规范",就是告诉子类必须要给抽象方法 ...

  5. java流程控制结构

    一.流程控制分三类 1. 顺序结构 - 程序是从上往下,从左往右执行 2. 选择结构(判断结构) - if语句 A. if(关系表达式){语句体} - 执行流程:成立就执行语句体,不成立就不执行 B. ...

  6. Android开发菜单以及子菜单

    package com.example.androidtest; import android.app.Activity; import android.os.Bundle; import andro ...

  7. pytest+requests+Python3.7+yaml+Allure+Jenkins+docker实现接口自动化测试

    接口自动化测试框架(用例自动生成) 项目说明 本框架是一套基于pytest+requests+Python3.7+yaml+Allure+Jenkins+docker而设计的数据驱动接口自动化测试框架 ...

  8. javascript初学笔记

    基本语句 赋值条件循环语句 javascript异常处理语句 trycatchfinally语句 Error对象 throw语句 函数 定义 调用 嵌套函数 函数的嵌套定义 内置函数 匿名函数和Fun ...

  9. JDK 动态代理的实现

    JDK 动态代理的实现 虽然在常用的 Java 框架(Spring.MyBaits 等)中,经常见到 JDK 动态代理的使用,也知道了怎么去写一个 JDK 动态代理的 Demo,但是并不清楚实现原理. ...

  10. Milking Time POJ - 3616 dp 感觉像背包

    #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> us ...