ural 1989 subplindromes
https://vjudge.net/problem/URAL-1989
题意:
先给出一个字符串,对于这个字符串,有两种操作,一种是询问从下标x到y的串是不是回文串,另一种是将下标为pos的字符改为另一种字符。
思路:
哎,看题解补的,还好学会了如何用hash判断回文串以及线段树单点更新在hash中的应用。
下面来详细讲讲吧。
首先,对于一个字符串,一共出现过n个不同的字符,那么就可以把这个字符串用n+1进制表示(考虑特殊元素0,比如bbaa,如果用26进制的话,那么就是1100,就会跟bb00起冲突,这一点要牢记)。因为这个n+1进制数表示为10进制数可能会很大,考虑无符号整型数,让其自然溢出,冲突的概率可以忽略不计(道听途说,这题反正没有问题)。
在这题中,随时需要计算某个串的10进制表示,所以就需要把27^0,27^1,27^2……预处理出来,在计算的时候就是O(1)的复杂度。
这题既然询问的是回文串,那么正向hash和反向hash都需要计算。之后,就用线段树来计算每一段字符串的hash值。当线段树建树的时候,递归到左右下标相等,那么此时就可以计算这个字符例如b的双向hash值,比如是字符串的长度是9,它的下标是3(注意字符串的下标从0开始,而线段树的最小下标是从1开始的),那么它的正向hash值就是000b,即为3 * (27) ^ 3,反向hash值就是00000b,即为 3 * (27) ^ 5。除了非真子树之外的其它节点的左hash,等于它的左儿子的左hash的值与右儿子的左hash的值的和,右hash类似。这样数就算建好了。
之后我们查询的时候,按照线段树的方式来查询就好了,不过有一个要注意的地方,举一个例子,字符串的长度为8,abcdasde,查询的是2到5,即为bcda是否为回文串,但是此时通过查询得到的左hash值是0bcda,右hash值是000adcb,所以他们的位数实际是不相等的,这里我们就需要做进一步的处理使得他们的位数相等才能做比较,这时候需要把0bcda,向右移两位,变成000bcda,如何移位呢,这里其实跟2进制的位运算有异曲同工之妙的,直接乘27^(相差的0的个数),实际就是x-1和n-y的差的绝对值了。(这里自己举个例子就很明显了。)之后再比较左hash和右hash就ok了。
更新的操作大概是这里面最简单的吧,不过不要忘记了向上更新的函数。
代码:
#include <stdio.h>
#include <string.h> #define N 100005
#define ll unsigned long long ll f[N];
int n; struct tree
{
int l,r;
ll suml,sumr;
} tree[N << ]; char s[N]; void pushup(int o)
{
tree[o].suml = tree[o << ].suml + tree[o << |].suml;
tree[o].sumr = tree[o << ].sumr + tree[o << |].sumr;
} void build(int o,int l,int r)
{
tree[o].l = l;
tree[o].r = r; if (l == r)
{
tree[o].suml = f[l-] * (s[l-] - 'a');
tree[o].sumr = f[n-l] * (s[l-] - 'a');
return;
} int m = (l + r) >> ; build(o << ,l,m);
build(o << | ,m+,r); pushup(o);
} ll suml,sumr; void query(int o,int l,int r)
{
if (tree[o].l >= l && tree[o].r <= r)
{
suml += tree[o].suml;
sumr += tree[o].sumr; return;
} int m = (tree[o].l + tree[o].r) >> ; if (m >= l) query(o << ,l,r);
if (m < r) query(o << |,l,r);
} void update(int o,int pos,int c)
{
if (tree[o].l == tree[o].r)
{
tree[o].suml = f[pos-] * c;
tree[o].sumr = f[n-pos] * c; return;
} int m = (tree[o].l + tree[o].r) >> ; if (pos <= m) update(o << ,pos,c);
if (pos > m) update(o << |,pos,c); pushup(o);
} int main()
{
f[] = ; for (int i = ;i < N;i++)
f[i] = f[i-] * ; scanf("%s",s); n = strlen(s); build(,,n); int num; scanf("%d",&num); for (int i = ;i < num;i++)
{
char a[]; scanf("%s",a); if (a[] == 'p')
{
suml = sumr = ; int x,y; scanf("%d%d",&x,&y); query(,x,y); int d1 = x - ;
int d2 = n - y; if (d1 > d2) sumr *= f[d1-d2];
else suml *= f[d2-d1]; if (sumr == suml) printf("Yes\n");
else printf("No\n");
}
else
{
char cc[]; int pos; scanf("%d%s",&pos,cc); update(,pos,cc[] - 'a');
}
} return ;
}
ural 1989 subplindromes的更多相关文章
- N - Subpalindromes URAL - 1989 哈希+线段树
N - Subpalindromes URAL - 1989 这个是一个哈希+线段树,这个题目也不算特别难,但是呢,还比较有意思. 这个题目给你两个操作,一个是回答l~r 区间是不是回文,一个是对一个 ...
- URAL 1989 Subpalindromes (多项式hash) +【线段树】
<题目链接> <转载于 >>> > 题目大意:给你一段字符串,进行两种操作:1.询问[l,r]这个区间中的字符串是否是回文串: 2.更改该字符串中对应下标的 ...
- 【URAL 1989】 Subpalindromes(线段树维护哈希)
Description You have a string and queries of two types: replace i'th character of the string by char ...
- ural 1989(树状数组+多项式hash)
题意:给出一个字符串.有两种操作,一个是p a b,问字符串从位置a到位置b的子串是否是一个回文子串.还有一个操作 c a b,把字符串位置a的字符替换为b. 题解:由于字符串长度为1e5且问的次数也 ...
- 线段树总结 (转载 里面有扫描线类 还有NotOnlySuccess线段树大神的地址)
转载自:http://blog.csdn.net/shiqi_614/article/details/8228102 之前做了些线段树相关的题目,开学一段时间后,想着把它整理下,完成了大牛NotOnl ...
- 后缀数组 POJ 3974 Palindrome && URAL 1297 Palindrome
题目链接 题意:求给定的字符串的最长回文子串 分析:做法是构造一个新的字符串是原字符串+反转后的原字符串(这样方便求两边回文的后缀的最长前缀),即newS = S + '$' + revS,枚举回文串 ...
- ural 2071. Juice Cocktails
2071. Juice Cocktails Time limit: 1.0 secondMemory limit: 64 MB Once n Denchiks come to the bar and ...
- ural 2073. Log Files
2073. Log Files Time limit: 1.0 secondMemory limit: 64 MB Nikolay has decided to become the best pro ...
- ural 2070. Interesting Numbers
2070. Interesting Numbers Time limit: 2.0 secondMemory limit: 64 MB Nikolay and Asya investigate int ...
随机推荐
- 【Windows 10 应用开发】使用快捷访问键
UWP 虽然主要面向触控操作,但 Windows 设备是万能工具,不用手指不用笔的时候,也可能会接上键盘耍耍.因此,给应用界面上的一些元素弄个快捷访问键也挺不错的.为了使用 Windows 上的各类应 ...
- HTTP协议 --- 图解三次握手过程
TCP(Transmission Control Protocol) 传输控制协议 TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接: 位码即tcp标志位,有6种标 ...
- Ubuntu下用cue文件对ape和wav文件自动分轨
很多音乐CD的镜像文件都带cue格式的分轨文件,在Ubuntu Linux下可以通过一些工具来实现自动分轨. 一.Ubuntu下需要安装的工具有flac,shntool,libav-tools $ s ...
- [0] 领域模型 VS 贫血模型
贫血→结构体领域→封装方法的类 1.领域模型 也要能够 到达解耦,最好不要出现billdao.InsertBill(obj)这种2.领域方法 最好是自身的方法,如改变一个属性值,添加一个子集,而不是一 ...
- django 调试 监控文件变化 自动刷新浏览器
问题描述:修改html js py等文件后,自动刷新浏览器,解放F5,提高效率 解决办法:使用gulp,使用bowerSync 关于gulp,可以查看系列教程 关于bowerSync,查看官网 关于结 ...
- CNN压缩:为反向传播添加mask(caffe代码修改)
神经网络压缩的研究近三年十分热门,笔者查阅到相关的两篇博客,博主们非常奉献的提供了源代码,但是发发现在使用gpu训练添加mask的网络上,稍微有些不顺,特此再进行详细说明. 此文是在 基于Caffe的 ...
- oracle备份、还原
----第一步:设置空表导出 ----由于Oracle 11G在用EXPORT导出时,空表不能导出.解决方法如下:(11G中有个新特性,当表无数据时,不分配segment,以节省空间) select ...
- CSS3学习系列之盒样式(二)
text-overflow属性 当通过把overflow属性的属性值设定为"hidden"的方法,将盒中容纳不下的内容隐藏起来时,如果使用text-overflow属性,可以在盒的 ...
- iOS基于AVPlayer的视频播放
基于 AVPlayer 自定义播放器http://www.cocoachina.com/ios/20160921/17609.html,http://www.2cto.com/kf/201608/53 ...
- 8.Smarty的条件判断语句的写法
{if $newObj eq 'a'} welcome a {elseif $a eq 'b'} welcome b {else} welcome others {/if}