zoukankan      html  css  js  c++  java
  • 【bzoj1014】 JSOI2008—火星人prefix

    http://www.lydsy.com/JudgeOnline/problem.php?id=1014 (题目链接)

    题意

      给出一个字符串,要求维护这些操作:询问后缀x与后缀y的LCQ(最长公共前缀),在第k个字符后插入一个字符,将第k个字符改成另一个字符。

    Solution

      对于修改与插入操作,我们用splay维护。考虑怎么求解LCQ。

      我们可以将字符串hash,然后平衡树上每一个节点的hash值就代表的该区间的hash值,毫无疑问,这是可以向上更新的。于是问题就解决了。

    细节

      注意splay中update的顺序。hash的进制要取好,不能比一位上的数范围小。hash值相乘的时候记得开long long。

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define inf 2147483640
    #define MOD 9875321
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=150010;
    int tr[maxn][2],fa[maxn],id[maxn],size[maxn];
    int v[maxn],h[maxn],bin[maxn];
    int n,rt,sz,q;
    char s[maxn];
    
    void update(int k) {
    	int l=tr[k][0],r=tr[k][1];
    	size[k]=size[l]+size[r]+1;
    	h[k]=h[l]+(LL)v[k]*bin[size[l]]%MOD+(LL)bin[size[l]+1]*h[r]%MOD;
    	h[k]%=MOD;
    }
    void rotate(int x,int &k) {
    	int y=fa[x],z=fa[y],l,r;
    	l=tr[y][1]==x;r=l^1;
    	if (y==k) k=x;
    	else tr[z][tr[z][1]==y]=x;
    	fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
    	tr[y][l]=tr[x][r];tr[x][r]=y;
    	update(y);update(x);
    }
    void splay(int x,int &k) {
    	while (x!=k) {
    		int y=fa[x],z=fa[y];
    		if (y!=k) {
    			if ((tr[z][0]==y) ^ (tr[y][0]==x)) rotate(x,k);
    			else rotate(y,k);
    		}
    		rotate(x,k);
    	}
    }
    int find(int k,int x) {
    	int l=tr[k][0],r=tr[k][1];
    	if (size[l]+1==x) return k;
    	else if (size[l]>=x) return find(l,x);
    	else return find(r,x-size[l]-1);
    }
    void insert(int k,int val) {
    	int x=find(rt,k+1),y=find(rt,k+2);
    	splay(x,rt);splay(y,tr[x][1]);
    	int z=++sz;tr[y][0]=z;fa[z]=y;v[z]=val;
    	update(z);update(y);update(x);
    }
    int query(int k,int val) {
    	int x=find(rt,k),y=find(rt,k+val+1);
    	splay(x,rt);splay(y,tr[x][1]);
    	return h[tr[y][0]];
    }
    int solve(int x,int y) {
    	int l=1,r=min(sz-x,sz-y)-1,ans=0;
    	while (l<=r) {
    		int mid=(l+r)>>1;
    		if (query(x,mid)==query(y,mid)) l=mid+1,ans=mid;
    		else r=mid-1;
    	}
    	return ans;
    }
    void build(int l,int r,int f) {
    	if (l>r) return;
    	int mid=(l+r)>>1,now=id[mid],last=id[f];
    	if (l==r) {
    		v[now]=h[now]=s[mid]-'a'+1;
    		fa[now]=last;size[now]=1;
    		tr[last][mid>=f]=now;
    		return;
    	}
    	build(l,mid-1,mid);build(mid+1,r,mid);
    	v[now]=s[mid]-'a'+1;fa[now]=last;update(now);
    	tr[last][mid>=f]=now;
    }
    int main() {
    	scanf("%s",s+2);
    	n=strlen(s+2);
    	bin[0]=1;for (int i=1;i<maxn;i++) bin[i]=bin[i-1]*31%MOD;
    	for (int i=1;i<=n+2;i++) id[i]=i;
    	build(1,n+2,0);rt=(n+3)>>1;sz=n+2;
    	scanf("%d",&q);
    	while (q--) {
    		int x,y;char ch[10];
    		scanf("%s",ch);
    		scanf("%d",&x);
    		if (ch[0]=='Q') scanf("%d",&y),printf("%d
    ",solve(x,y));
    		if (ch[0]=='R') {
    			scanf("%s",ch);
    			x=find(rt,x+1);splay(x,rt);
    			v[rt]=ch[0]-'a'+1;update(rt);
    		}
    		if (ch[0]=='I') scanf("%s",ch),insert(x,ch[0]-'a'+1);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    C# tcp发送十六进制数据
    WPF中通过AForge实现USB摄像头拍照
    借鉴过的别人的帖子之C#篇
    C# 连续的语音识别
    C# NAudio 录音
    AS3 水波纹
    ARM多核心集群服务器
    RK3399Pro Android Rock-X 人工智能开发系列(2)
    智能化连锁门店解决方案
    RK3399Pro Android Rock-X 人工智能开发系列(1)
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/5974174.html
Copyright © 2011-2022 走看看