• [BZOJ1014][JSOI2008]火星人prefix


    bzoj
    luogu

    题意

    给你一个串,支持三种操作:
    1、在一个位置插入一个字符。
    2、把一个位置的字符修改。
    3、查询两个后缀的(lcp)
    任意时候字符串长度(le 10^5),询问操作(le 10^4),总操作数(le 1.5*10^5)

    sol

    二分+(hash)。只要在(splay)上维护一个区间的(hash)值就可以了。
    每次二分一个长度后直接把两个(lcp)对应的区间区间(split)出来然后判断。复杂度两个(log)

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define ull unsigned long long
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 1e5+5;
    const int base = 1705;
    int n,m,fa[N],ch[2][N],key[N],sz[N],root;ull pw[N],hash[N];
    char s[N];
    bool son(int x){return x==ch[1][fa[x]];}
    void pushup(int x)
    {
    	hash[x]=hash[ch[0][x]]*pw[sz[ch[1][x]]+1]+key[x]*pw[sz[ch[1][x]]]+hash[ch[1][x]];
    	sz[x]=sz[ch[0][x]]+sz[ch[1][x]]+1;
    }
    void rotate(int x)
    {
    	int y=fa[x],z=fa[y],c=son(x);
    	ch[c][y]=ch[c^1][x];if (ch[c][y]) fa[ch[c][y]]=y;
    	fa[x]=z;if (z) ch[son(y)][z]=x;
    	ch[c^1][x]=y;fa[y]=x;pushup(y);
    }
    void splay(int x,int goal)
    {
    	for (int y=fa[x];y!=goal;rotate(x),y=fa[x])
    		if (fa[y]!=goal) son(x)^son(y)?rotate(x):rotate(y);
    	pushup(x);if (!goal) root=x;
    }
    int find(int k,int goal)
    {
    	int x=root;
    	while (base){
    		if (k<=sz[ch[0][x]]) x=ch[0][x];
    		else if (k==sz[ch[0][x]]+1) {splay(x,goal);return x;}
    		else k-=sz[ch[0][x]]+1,x=ch[1][x];
    	}
    }
    int build(int l,int r,int ff)
    {
    	if (l>r) return 0;
    	int mid=l+r>>1;
    	key[mid]=s[mid];fa[mid]=ff;
    	ch[0][mid]=build(l,mid-1,mid);
    	ch[1][mid]=build(mid+1,r,mid);
    	pushup(mid);return mid;
    }
    ull cal(int l,int r)
    {
    	find(l,0);find(r+2,root);
    	return hash[ch[0][ch[1][root]]];
    }
    int main()
    {
    	pw[0]=1;
    	for (int i=1;i<N;++i) pw[i]=pw[i-1]*base;
    	scanf("%s",s+2);n=strlen(s+2);
    	root=build(1,n+2,0);
    	m=gi();n+=2;
    	while (m--)
    	{
    		char opt=getchar();
    		while (opt!='Q'&&opt!='R'&&opt!='I') opt=getchar();
    		if (opt=='Q')
    		{
    			int x=gi(),y=gi();if (x>y) swap(x,y);
    			int l=1,r=n-y-1,ans=0;
    			while (l<=r)
    			{
    				int mid=l+r>>1;
    				if (cal(x,x+mid-1)==cal(y,y+mid-1)) ans=mid,l=mid+1;
    				else r=mid-1;
    			}
    			printf("%d
    ",ans);
    		}
    		if (opt=='R')
    		{
    			int x=gi();x=find(x+1,0);
    			key[x]=getchar();pushup(x);
    		}
    		if (opt=='I')
    		{
    			int x=gi(),y=find(x+1,0),z=find(x+2,root);
    			key[++n]=getchar();ch[0][fa[n]=z]=n;
    			splay(n,0);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    关于Java 下 Snappy压缩存文件
    英文分词和中文分词
    vuex requires a Promise polyfill in this browser
    Vue 中 export default 和 module.exports
    Linux 进程以及多线程的支持
    mysqldump
    linux磁 盘分区 挂载
    ubuntu16.04挂载windows NTFS磁盘方法
    Linux服务管理 systemctl命令详解
    nextcloud 安装
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8820773.html
Copyright © 2020-2023  润新知