1. 程式人生 > >ural1989 單點更新+字串hash

ural1989 單點更新+字串hash

正解是雙雜湊,不過一次雜湊也能解決。。

然後某個數字就對應一個字串,雖然有些不同串對應同一個數字,但是概率非常小,可以忽略不計。從左到右、從右到左進行兩次hash,如果是迴文串,那麼對應的整數必定存在某種關係(可以理解成相等),對於更新操作,就是單點更新。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#include<algorithm>
#define ll unsigned long long 
#define lson l,m,rt<<1
#define
rson m+1,r,rt<<1|1 #define maxn 100005 char s[maxn]; ll F[maxn+1]; int len; struct node{ ll suml,sumr; }tree[maxn<<2];//區間儲存從左到右和從右到左的hash值 inline void pushup(int rt){ tree[rt].suml=tree[rt<<1].suml+tree[rt<<1|1].suml; tree[rt].sumr=tree[rt<<1].sumr+tree[rt<<1
|1].sumr; } void build(int l,int r,int rt){ if(l==r){ tree[rt].suml=F[l-1]*(s[l-1]-'a'); tree[rt].sumr=F[len-l]*(s[l-1]-'a'); return; } int m=l+r>>1; build(lson); build(rson); pushup(rt); } void update(int pos,int val,int l,int r,int rt){//單點更新 if
(l==r){ tree[rt].suml=F[l-1]*val; tree[rt].sumr=F[len-l]*val; return; } int m=l+r>>1; if(pos<=m) update(pos,val,lson); else update(pos,val,rson); pushup(rt); } ll suml,sumr; void query(int x,int y,int l,int r,int rt){ if(x<=l && y>=r){ suml+=tree[rt].suml; sumr+=tree[rt].sumr; return; } int m=l+r>>1; if(x<=m) query(x,y,lson); if(y>m) query(x,y,rson); } int main(){ F[0]=1; for(int i=1;i<=maxn;i++) F[i]=F[i-1]*27;//打表處理 int q; while(scanf("%s",s)!=EOF){ scanf("%d",&q); len=strlen(s); build(1,len,1); char op[20]; int x,y; while(q--){ scanf("%s",op); if(op[0]=='p'){//查詢 scanf("%d%d",&x,&y); suml=sumr=0; query(x,y,1,len,1); int k1=x-1;//左到右的長度 int k2=len-y;//右到左的區間長度 if(k1>k2) sumr*=F[k1-k2]; else suml*=F[k2-k1]; cout<<suml<<" "<<sumr<<endl; if(suml==sumr) puts("YES"); else puts("NO"); } else {//單點修改 int x; char tmp[2]; scanf("%d%s",&x,tmp); update(x,tmp[0]-'a',1,len,1); } } } return 0; }