题目链接:http://acdream.info/problem?

pid=1019

题意:两种操作,第一种将字符串某个位置的字符换为还有一个字符。另外一种查询某个连续子序列是否是回文串;

解法:有两种hash的办法,所以写了两种解法;首先hash是x1 * p^1+ x2*p^2 +x3*p^3...能够用树状数组维护前缀和,维护两个串,一个是正串。还有一个是反串用于比較。比較时候乘以对应的p倍数推断是否相等。

刘汝佳白书上的hash方法处理这道题更复杂:改动i会对后缀j产生的影响为a*p^(i-j),那么把这个式子变成a * p^i *p^(-j)  然后就是在这个位置加上a * p^i,以后查询每一个i位置的hash值后都乘以p^i.

第一分代码:

/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std; #define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef unsigned long long LL;
const int Max=1000010;
const int INF=1e9+7;
char s[Max];
LL C[2][Max];
LL Hash[Max];
int seed=13;
void init()
{
Hash[0]=1;
for(int i=1; i<Max; i++)
Hash[i]=Hash[i-1]*seed;
}
int len;
void update(int i,int pos,LL data)
{
while(pos<=len)
{
C[i][pos]+=data;
pos+=pos&(-pos);
}
}
LL get(int i,int pos)
{
LL ans=0;
while(pos)
{
ans+=C[i][pos];
pos-=pos&(-pos);
}
return ans;
}
LL gethash(int i,int l,int r)
{
return get(i,r)-get(i,l-1);
}
int main()
{
init();
while(scanf("%s",s+1)==1)
{
memset(C,0,sizeof C);
int t;
cin>>t;
len=strlen(s+1);
for(int i=1; i<=len; i++)
{
update(0,i,(s[i]-'a')*Hash[i]);
update(1,len+1-i,(s[i]-'a')*Hash[len+1-i]);
}
while(t--)
{
char c;
getchar();
scanf("%c",&c);
if(c=='C')
{
char b[5];
int a;
scanf("%d%s",&a,b);
update(0,a,-(s[a]-'a')*Hash[a]);
update(0,a,(b[0]-'a')*Hash[a]);
update(1,len+1-a,-(s[a]-'a')*Hash[len+1-a]);
update(1,len+1-a,(b[0]-'a')*Hash[len+1-a]);
s[a]=b[0];
}
else
{
int l,r;
scanf("%d%d",&l,&r);
if(gethash(0,l,r)*Hash[len-l]==gethash(1,len+1-r,len+1-l)*Hash[r-1])
puts("yes");
else
puts("no");
}
}
}
return 0;
}

第二份代码:

/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std; #define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef unsigned long long LL;
const int Max=1000010;
const LL INF=1000000007;
char s[Max];
char s2[Max];
LL Hash[Max];
LL C[Max];
LL C2[Max];
int seed=13;
int len;
void init()
{
Hash[0]=1;
for(int i=1; i<Max; i++)
Hash[i]=(Hash[i-1]*seed)%INF;
}
LL pow1(LL a,LL k)
{
LL ans=1;
while(k)
{
if(k&1)
ans=(ans*a)%INF;
a=(a*a)%INF;
k>>=1;
}
return ans;
}
void update(int pos,LL value)
{
while(pos!=0)
{
C[pos]=(C[pos]+value+INF)%INF;
pos-=pos&(-pos);
}
}
void update2(int pos,LL value)
{
while(pos!=0)
{
C2[pos]=(C2[pos]+value+INF)%INF;
pos-=pos&(-pos);
}
}
LL query(int pos)
{
LL ans=0;
while(pos<=len+1)
{
ans=(ans+C[pos])%INF;
pos+=pos&(-pos);
}
return ans;
}
LL query2(int pos)
{
LL ans=0;
while(pos<=len+1)
{
ans=(ans+C2[pos])%INF;
pos+=pos&(-pos);
}
return ans;
}
LL get(int now)
{
LL ans=query(now);
return (pow1(pow1(seed,now),INF-2)%INF*ans)%INF;
}
LL gethash(int l,int r)
{
return (get(l)-get(r+1)*Hash[r+1-l]%INF+INF)%INF;
}
LL get2(int now)
{
LL ans=query2(now);
return (pow1(pow1(seed,now),INF-2)%INF*ans)%INF;
}
LL gethash2(int l,int r)
{
return (get2(l)-get2(r+1)*Hash[r+1-l]%INF+INF)%INF;
}
int main()
{
init();
while(scanf("%s",s+1)==1)
{
int t;
scanf("%d",&t);
len=strlen(s+1);
strcpy(s2+1,s+1);
reverse(s2+1,s2+len+1);
memset(C,0,sizeof C);
memset(C2,0,sizeof C2);
for(int i=1; i<=len; i++)
{
update(i,(s[i]-'a')*Hash[i]%INF);//a*x^(i-j)=a*x^i*(x^-j);
update2(i,(s2[i]-'a')*Hash[len+1-i]%INF);
}
while(t--)
{
char c[5];
scanf("%s",c);
//printf(c);
if(c[0]=='C')
{
int a;
char b[5];
scanf("%d%s",&a,b);
update(a,('a'-s[a])*Hash[a]%INF);
update(a,(b[0]-'a')*Hash[a]%INF);
update2(len+1-a,('a'-s2[len+1-a])*Hash[len+1-a]%INF);
update2(len+1-a,(b[0]-'a')*Hash[len+1-a]%INF);
s[a]=b[0];
s2[len+1-a]=b[0];
}
else
{
int l;
int r;
scanf("%d%d",&l,&r);
if(r-l<=1)
{
puts("yes");
continue;
}
if(gethash(l,r)==gethash2(len+1-r,len+1-l))
puts("yes");
else
puts("no");
}
}
}
return 0;
}

ACdreamoj 1011(树状数组维护字符串hash前缀和)的更多相关文章

  1. 【BZOJ2124】等差子序列 树状数组维护hash值

    [BZOJ2124]等差子序列 Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N ...

  2. 第十二届湖南省赛G - Parenthesis (树状数组维护)

    Bobo has a balanced parenthesis sequence P=p 1 p 2…p n of length n and q questions. The i-th questio ...

  3. BZOJ 3881 [COCI2015]Divljak (Trie图+Fail树+树链的并+树状数组维护dfs序)

    题目大意: Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  4. [poj3378] Crazy Thairs (DP + 树状数组维护 + 高精度)

    树状数组维护DP + 高精度 Description These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ...

  5. HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5869 问你l~r之间的连续序列的gcd种类. 首先固定右端点,预处理gcd不同尽量靠右的位置(此时gc ...

  6. POJ 3321 Apple Tree(后根遍历将树转化成序列,用树状数组维护)

    题意:一棵树,有很多分叉,每个分叉上最多有1个苹果. 给出n,接下来n-1行,每行u,v,表示分叉u,v之间有树枝相连.这里数据中u相当于树中的父节点,v相当于子节点. 给出两个操作: 1.C x  ...

  7. LOJ107. 维护全序集【树状数组维护全序集】

    题目描述 这是一道模板题,其数据比「普通平衡树」更强. 如未特别说明,以下所有数据均为整数. 维护一个多重集 S ,初始为空,有以下几种操作: 把 x 加入 S 删除 S 中的一个 x,保证删除的 x ...

  8. ACM-ICPC 2018 徐州赛区网络预赛 G. Trace【树状数组维护区间最大值】

    任意门:https://nanti.jisuanke.com/t/31459 There's a beach in the first quadrant. And from time to time, ...

  9. Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2) C. Fountains 【树状数组维护区间最大值】

    题目传送门:http://codeforces.com/contest/799/problem/C C. Fountains time limit per test 2 seconds memory ...

随机推荐

  1. php 字符串重要函数

    1.chop() 从字符串右端移除字符 chop(string,charlist) $str="hello world~"; echo chop($str,"ld~&qu ...

  2. 洛谷P1160 队列安排

    题目描述 一个学校里老师要将班上N个同学排成一列,同学被编号为1-N,他采取如下的方法: 1.先将1号同学安排进队列,这时队列中只有他一个人: 2.2-N号同学依次入列,编号为i的同学入列方式为:老师 ...

  3. Hidden (NOIP模拟赛)(字符串模拟QAQ)

    原题传送门 神奇的题目诶 原来以为字符串比较一定要O(NlogN) 结果发现可以均摊O(N) 首先我们来讲一讲原理 我们有3个指针i,j,k i=0,j=1,k=0 一开始我们不断对k+1直到找到ch ...

  4. Python学习杂记_12_函数(三)

    内置函数 Python有很多内置函数,以下这些是常用且必须要掌握的: 强制类型转换: bool() # 把一个对象转换成布尔类型 int() # 整形 float() # 小数 str() # 字符 ...

  5. WPF+MVVM数据绑定问题集锦

    1.  数据绑定的问题 在使用数据绑定时,一般使用 ObservableCollection<T> 类,不使用list列表集合,因为list数据发生变化时,UI界面不更新,而Observa ...

  6. 利用js将图片地址进行转义

    利用js将图片地址进行转义 在业务中经常需要将图片从后台获取,然后在前台显示.其中后台存取图片主要分为两种,一种是数据库中获取图片的地址,第二种是存取图片内容的信息.这次主要是前台代码处理第一种情况. ...

  7. Guava源码学习(五)EventBus

    基于版本:Guava 22.0 Wiki:EventBus 0. EventBus简介 提供了发布-订阅模型,可以方便的在EventBus上注册订阅者,发布者可以简单的将事件传递给EventBus,E ...

  8. HDU 6312.Game-博弈-签到题 (2018 Multi-University Training Contest 2 1004)

    2018 Multi-University Training Contest 2 6312.Game 博弈,直接官方题解,懒了. 考虑将游戏变成初始时只有2~n,如果先手必胜的话,那么先手第一步按这样 ...

  9. 51nod 1420 数袋鼠好有趣【贪心】

    1420 数袋鼠好有趣 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 有n只袋鼠.每只袋鼠的大小用一个整数表示. ...

  10. POJ 3080-Blue Jeans【kmp,字符串剪接】

    Blue Jeans Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20695   Accepted: 9167 Descr ...