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 ...
随机推荐
- 记一次调试串口设备Bug的经历
最近花了差不多1天的时间在折腾一个Bug,该Bug的表象如下: 这个Bug还特别独特,在开发电脑中无提示,在终端用户那里每次使用软件的时候都报这个.仔细思考了一下最近在源码中新添加的功能,没发现有啥特 ...
- java入门学习笔记之1(类的定义,代码的编译执行)
这篇文章讲解Java代码的基本执行过程 我们先抛开各种JAVA IDE,开发工具,只使用文本编辑器,以突出最本质的东西. 在Linux环境下,我们编辑一个文件: vim HelloWorld.java ...
- “前”方有坑,绕道而行(一)-- H5+CSS
1. 关于 数字.英文 不换行问题: 情景:昨天测试 小程序,输入英文,没有换行,且 下方有横向滚动条: 解决:word-break: word-break:break-all; /*只对英文起作用 ...
- JVM中class文件探索与解析(一)
一直想成为一名优秀的架构师的我,转眼已经工作快两年了,对于java内核了解甚少,闲来时间,看看JVM,吧自己的一些研究写下来供大家参考,有不对的地方请指正. 废话不多说,一起来看看JVM中类文件是如何 ...
- Streaming输入输出
Structured Streaming 输入输出 输入 SparkSession.readStream() 返回一个 DataStreamReader 接口对象,可以通过该对象对输入源进行参数配置, ...
- 在jupyter notebook中同时安装python2和python3
之前讨论过在anaconda下安装多个python版本,本期来讨论下,jupyter notebook中怎样同时安装python2.7 和python3.x. 由于我之前使用的jupyter note ...
- 2.如何使用matlab拟合曲线
输入数据 做数据曲线拟合,当然该有数据,本经验从以如下数据作为案例. 添加数据到curve fitting程序 这一步就是将你要拟合的数据添加到curve fitting程序中,同时给你拟合的曲线 ...
- ==,=和equals()区别
equals和=,==的区别 一. ==和equals的区别 1. ==是运算符 2. equals是String对象的方法 一般有两种类型的比较 1. 基本数据类型的比较 2. 引用对象的比较 ...
- C#窗体多语言切换(简繁)
多窗体最好继承一个父窗体,在父窗体Load事件中执行此方法 添加引用 using Microsoft.VisualBasic; #region 语言切换 /// <summary> /// ...
- LR监控Windows Server 2008 R2系统资源提示“指定的网络名不可用。”
问题现象: LR监控远程服务器Window Server 2008 R2 系统资源,提示“Monitor name :Windows Resources. Cannot connect to mach ...