Trie——解决字符串搜索、异或最值问题

  • 在说到Trie之前,我们设想如下问题:

给我们1e5个由小写字母构成的不重复的字符串,每个字符串长度不超过6,之后是1e5次查询操作,每次给我们一个字符串,要求我们判断这个字符串是否出现过,如果是则求出它是多少个其他的字符串的前缀,并在之后的操作中无视这个字符串(删除)。

  • 查询是否出现这个可以用set或者hash,但是前缀,,其实也有办法,但是这里要介绍的方法是使用一种易于理解的数据结构——Trie

建立Trie

  • 字典树Trie的结构比较自然,如对于字符串集合{"abca", "ab", "bcd", "abcde", "bcde", "bcdf"},可以建立一棵这样的Trie:

可知:

- 每一条边代表一个字符
- 节点不为0代表从根节点到此为一个完整的字符串

实现的方法也比较简单,建立一棵单向树,每个节点都有

  • 26个子节点(所有小写字母);

  • 一个isstr,bool值,代表这里是否为一个字符串的结束

  • 一个vis,int值,代表到这里已经有多少个字符串遍历过(是多少字符串的前缀)

一开始树为空,我们每得到一个字符串,就从它的第一个字符开始,从根节点遍历,没有对应的节点就创建,同时把所经过的节点的vis值加一,到最后字符串终止时,在终止的节点处置isstr为true。

更多操作

1.查询

从树的形状就可以看出,这是一棵专门查询字符串存在与否的数据结构(同时也付出了巨大的空间代价)。查询操作很简单,从根节点开始,按照要查询的字符串的每一位来遍历,如果遇到空节点或者终止时的节点的isstr为false,则字符串不存在,否则存在。

2.查询某个串是多少个字符串的前缀

这个就是读取要查询的字符串的终止节点的vis值即可

3.删除某个字符串

首先查询成功之后,我们从底部开始回溯删除这个串的信息,将终止节点的isstr置为false,同时将路过的vis值减一,如果vis值减为0则将将此节点在其父节点中删除即可。

01Trie解决xor最值问题

原题链接

题意

给我们一个序列A和序列B,要求我们找到B序列的一种排列,使得

\[C_i \quad xor \quad B_i == A_i
\]

中的序列C字典序最小,并输出序列C,长度<=3e5,每个数小于2^30

思路

  • 首先按照运算规则C xor B == A意味着A xor B == C 也就是说 寻找一种B的排列,使得A逐个与B异或的结果的字典序最小

  • 3e5基本不可能在其他操作中间搞什么排序了,应该从异或运算的结果出发,我们追求结果的字典序最小,也就是说,对于每个Ai,我们都要找到一个Bj,使得其异或结果最小。这个如果直接找的话,是比较难的。但是如果使用Trie的话,可以直接求得每一个Ai的最小结果,方法如下:

    • 对B序列建立一棵只包含01字符的Trie(也就是二叉树),我们规定A与B的每一个数都是30位二进制数,左边补零,从左边的第一位开始建树。

    • B序列的01Trie建好之后,对A序列从1到n每个数都按位在Trie中遍历,一开始先设ans为0,之后优先走与当前自己的二进制位相同的边,如果没有则让ans或上这一位的1。(确保ans尽可能地小)

    • 之后输出这个ans,并将走过的路线所代表的Bi删除掉就可以

  • 可以看出时间复杂度为

    \[O(30*n)
    \]

  • 对空间复杂度来说,不要使用满二叉树的存储方式,使用动态开点的方式,空间复杂度不超过

    \[O(30*n)
    \]

01Trie代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; int n;
int aa[10000005][2] = {{0}}, vv[10000005][2] = {{0}}, co = 1;
int A[300005] = {0}; void add(int x)
{
int o = 1;
for (int i = 29; i >= 0; --i)
{
int bitt = (x >> i) & 1;
if (!aa[o][bitt])
{
aa[o][bitt] = ++co;
}
++vv[o][bitt];
o = aa[o][bitt];
}
} int trie(int x)
{
int o = 1, ans = 0;
for (int i = 29; i >= 0; --i)
{
int bitt = (x >> i) & 1;
if (vv[o][bitt])
{
--vv[o][bitt];
o = aa[o][bitt]; }
else
{
--vv[o][bitt ^ 1];
o = aa[o][bitt ^ 1];
ans |= (1 << i);
}
}
return ans;
} int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &A[i]);
}
for (int i = 1; i <= n; ++i)
{
int xx;
scanf("%d", &xx);
add(xx);
}
for (int i = 1; i < n; ++i)
{
printf("%d ", trie(A[i]));
}
printf("%d", trie(A[n]));
return 0;
}

Trie——解决字符串搜索、异或最值问题的更多相关文章

  1. C#下利用正则表达式实现字符串搜索功能的方法(转)

    关键字:正则表达式.元字符.字符串.匹配: 1.正则表达式简介:正则表达式提供了功能强大.灵活而又高效的方法来处:.NET框架正则表达式并入了其他正则表达式实现的: 2.字符串搜索:正则表达式语言由两 ...

  2. 如果不空null并且不是空字符串才去修改这个值,但这样写只能针对字符串(String)类型,如果是Integer类型的话就会有问题了。 int i = 0; i!=''。 mybatis中会返回tr

    mybatis 参数为Integer型数据并赋值0时,有这样一个问题: mybatis.xml中有if判断条件判断参数不为空时,赋值为0的Integer参数被mybatis判断为空,因此不执行< ...

  3. Linux常用命令学习2---(文件搜索命令locate find、命令搜索命令whereis which、字符串搜索命令grep、帮助命令man)

     1.文件搜索命令:locate [文件名]    在后台数据库中按文件名搜索,搜索速度比find快,耗费资源更少    例子:locate test.txt,就会显示文件名包含 test.txt的所 ...

  4. gerrit session expired 怎么解决,搜索未果

    gerrit session expired,怎么解决,搜索未果

  5. jsoncpp封装和解析字符串、数字、布尔值和数组

    使用jsoncpp进行字符串.数字.布尔值和数组的封装与解析. 1)下载jsoncpp的代码库 百度网盘地址 :http://pan.baidu.com/s/1ntqQhIT 2)解压缩文件 json ...

  6. C#入门篇6-7:字符串操作 看看字符串的特殊之处 值类型与引用类型的区别

    //看看字符串的特殊之处值类型与引用类型的区别 public static void CompareString(string stra, string strb, int i) { #region ...

  7. 解决dede搜索页面只能显示10条信息解决方案

    解决dede搜索页面只能显示10条信息解决方案,感觉显示的信息太少,这时就要想办法去解决一下.看看有什么好办法来解决一下这个问题. dede搜索页模板中,默认只能显示10条记录. 打开dede搜索页模 ...

  8. 【ToolGood.Words】之【StringSearch】字符串搜索——基于BFS算法

    字符串搜索中,BFS算法很巧妙,个人认为BFS算法效率是最高的. [StringSearch]就是根据BFS算法并优化. 使用方法: string s = "中国|国人|zg人|fuck|a ...

  9. xsank的快餐 » Python simhash算法解决字符串相似问题

    xsank的快餐 » Python simhash算法解决字符串相似问题 Python simhash算法解决字符串相似问题

随机推荐

  1. PHP|PHP之代码编写规范

    PHP之代码编写规范 一.编辑器设置 1.使用Tab缩进(四个空格),不要直接使用空格 2.文件编码格式 二.命名设置 1.公共库名称空间 2.变量命名 2.1.所有字母都使用小写 2.2.首字母根据 ...

  2. 升级OPENSSH踩过的坑

    安装三个必要依赖包yum install gcc zlib-devel openssl-devel上传安装包,创建一个/tmp目录下,然后解压,将/etc/ssh/目录移动到本地解压安装包,进入安装目 ...

  3. Spring事务方法上增加synchronized真的有效果吗?

    此文转载,Spring事务本身是一个非常复制的问题,再加上线程并发处理就更加要主要了,由于再开发中有很多朋友会范与下文同样的错误,因分享给大家. 前言 Spring事务的一个奇怪的问题. 朋友问了我一 ...

  4. 恕我直言你可能真的不会java第5篇:Stream的状态与并行操作

    一.回顾Stream管道流操作 通过前面章节的学习,我们应该明白了Stream管道流的基本操作.我们来回顾一下: 源操作:可以将数组.集合类.行文本文件转换成管道流Stream进行数据处理 中间操作: ...

  5. spring boot 和shiro的代码实战demo

    spring boot和shiro的代码实战 首先说明一下,这里不是基础教程,需要有一定的shiro知识,随便百度一下,都能找到很多的博客叫你基础,所以这里我只给出代码. 官方文档:http://sh ...

  6. LeetCode65. 有效数字

    这题完美的诠释了什么叫"面向测试用例编程".由于要考虑的情况很多,所以基本的思路是先根据给出的测试用例写出规则判断无效的情况,然后再根据提交的错误对剩下的情况进行特判,如果不满足所 ...

  7. socket 建立网络连接,client && server

    client代码: package socket; import java.io.IOException; import java.net.Socket; /** * 客户端_聊天室 * * @aut ...

  8. Data types 'int' and 'float'

    The type int means that the variables listed are integers; by contrast with float, which means float ...

  9. 同一WpfApplication下简单的页面转换

    别人写的很不错的Dome...分享学习下 源文件地址 : http://pan.baidu.com/share/link?shareid=1698564707&uk=3912660076

  10. css图片居中,通过纯css实现图片居中的多种实现方法

    在网页布局中,图文排版是我们常用的,那么经常会遇到如何让图片居中显示呢,这篇文章将总结常用css实现图片居中的方法总结: html结构: <div class="demo" ...