题目链接: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. redis的五种基本数据类型

    redis基本数据类型 redis一共分为5中基本数据类型:String,Hash,List,Set,ZSet 第一种String String类型是包含很多种类型的特殊类型,并且是二进制安全的.比如 ...

  2. error MSB3073 解决方法(转)

    原文转自 http://blog.csdn.net/yangjie569889321/article/details/28488151 最近将VC2002 代码移植到VC2010,出现编译错误:1&g ...

  3. 谈谈dpdk应用层包处理程序的多进程和多线程模型选择时的若干考虑

    看到知乎上有个关于linux多进程.多线程的讨论:http://www.zhihu.com/question/19903801/answer/14842584 自己项目里也对这个问题有过很多探讨和测试 ...

  4. LVM更换硬盘

    #检测坏道 smartctl -a /dev/sdd #硬盘检测 e2fsck -f /dev/mapper/vg_root-lv_data #重新定义空间大小,将原来的大小上减去要移走的硬盘 res ...

  5. 从linux看Android之一--init进程

    准备环境: 熟悉linux环境和shell脚本 用SSHDROID和XShell搭建android的命令行环境(帮助找到熟悉的linux界面,因为android删除了很多标准linux平台上很多的sh ...

  6. Oracle sql例子

    create database oracle1 )) select * from class ,'一班') ,'二班') ,'三班') --创建学生表 ),cid int ,constraint FK ...

  7. centos7 svn服务器搭建

    系统环境:centos 7.5 yum安装svn yum install subversion -y 创建svn 版本库目录 mkdir -p /var/svn/svnrepos 在版本库目录下创建版 ...

  8. centos7部署nagios

    一.Nagios简介 Nagios是一款开源的电脑系统和网络监视工具,能有效监控Windows.Linux和Unix的主机状态,交换机路由器等网络设置,打印机等.在系统或服务状态异常时发出邮件或短信报 ...

  9. Starting MySQL... ERROR! The server quit without updating PID file 问题解决

    今天遇到一个mysql起不来,不知为啥挂了,启动是下面的报错 Starting MySQL... ERROR! The server quit without updating PID file 后来 ...

  10. 这篇 感觉很实用--DJANGO ORM

    Django之model F/Q以及多对多操作 http://www.cnblogs.com/ccorz/p/5882400.html model之F/Q操作 F操作,使用查询条件的值 打个比方吧,有 ...