bzoj 1014: [JSOI2008]火星人prefix

本文分享了一道关于Splay树维护字符串Hash值的问题解答,通过中序遍历实现,并结合二分查找来确定最长子串长度。文章详细介绍了如何使用Splay树处理字符串操作,包括查询、替换和插入等,提供了完整的C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

这道题告诉我 

提交代码之前 请检查自己改注释掉的printf注释掉没有。。。

输出前的Tab删掉没有。。。

/**************************************************************
    Problem: 1014
    User: lxy8584099
    Language: C++
    Result: Accepted
    Time:6872 ms
    Memory:4828 kb
****************************************************************/
 
/*
    以为是后缀相关的题 不敢做 
    但是偷偷瞄了眼题解 居然和后缀一点关系都没有
    splay维护字符串的hash值 (中序遍历
    二分最长长度   (自己想的话完全想不到平衡树 QwQ 
*/
#include<cstdio>
#include<cstring>
#define lc (c[x][0])
#define rc (c[x][1])
#define mid ((l+r)>>1)
#define ull unsigned long long
using namespace std;
const int N=1e5+50;
int T,l,tot;
ull B=10007,base[N]={1};
ull val[N],hash[N];
int c[N][2],size[N],root,fa[N];
char str[N],ch[10];
void push_up(int x)
{
    size[x]=size[lc]+size[rc]+1;
    hash[x]=hash[lc]*base[size[rc]+1]+
            val[x]*base[size[rc]] + hash[rc];
}
void rotate(int x)
{
    int y=fa[x],z=fa[y],sx=c[y][1]==x;
    int sy=c[z][1]==y,w=c[x][sx^1];
    fa[w]=y;c[y][sx]=w; fa[y]=x;c[x][sx^1]=y;
    fa[x]=z;c[z][sy]=x;  push_up(y);push_up(x);
}
void splay(int x,int goal)
{
    if(x==goal) return ;
    while(fa[x]!=goal)
    {
        int y=fa[x],z=fa[y];
        if(z!=goal)
            rotate((c[y][1]==x)^(c[z][1]==y)?(x):(y));
        rotate(x);
    }
    if(goal==0) root=x;
}
int build(int f,int l,int r)
{
    if(l>r) return 0; 
    int x=++tot;val[x]=hash[x]=str[mid];
    lc=build(x,l,mid-1); rc=build(x,mid+1,r);
    size[x]=1; fa[x]=f; push_up(x); return x;
}
int find(int x,int k)
{
    if(k<=size[lc]) return find(lc,k);
    if(k<=size[lc]+1) return x;
    k-=(size[lc]+1);return find(rc,k);
}
ull find_hash(int k,int len) // k开始的len长的字符串 
{
    int p1=find(root,k),p2=find(root,k+len+1);
    splay(p1,0);splay(p2,p1);
//  printf("%llu\n",hash[c[p2][0]]);
    return hash[c[p2][0]];
}
int query(int i,int j)
{
    int ans=0,l=1,r=tot-j-1;
    while(l<=r)
    {
        int md=(l+r)>>1;
        if(find_hash(i,md)==find_hash(j,md))
        {ans=md;l=md+1;} 
        else r=md-1;
    } return ans;
}
void change(int k,int c) 
{
    int x=find(root,k+1);splay(x,0);
    val[x]=hash[x]=c; push_up(x);
}
void insert(int k,int v)
{
    int p1=find(root,k+1);splay(p1,0);
    int p2=c[p1][1];  while(c[p2][0]) p2=c[p2][0];
    splay(p2,p1); int x=++tot; fa[x]=p2; c[p2][0]=x;
    val[x]=hash[x]=v;size[x]=1; push_up(p2); push_up(p1);
}
void dfs(int x); 
int main()
{
    scanf("%s",str+2); l=strlen(str+2);
//  printf("l:%d\n",l);
    str[1]=str[l+2]='A';
    for(int i=1;i<=100001;i++) base[i]=base[i-1]*B;
    root=build(0,1,l+2);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",ch);
        int x,y; char s[10];
        if(ch[0]=='Q') 
        {
            scanf("%d%d",&x,&y);
            if(x>y) x^=y^=x^=y;
            printf("%d\n",query(x,y));
        }
        else if(ch[0]=='R')
        {
            scanf("%d",&x);scanf("%s",s);
            change(x,(int)(s[0]));
        }
        else if(ch[0]=='I')
        {
            scanf("%d",&x);scanf("%s",s);
            insert(x,(int)(s[0]));
        }
    }
//  dfs(root); printf("\n");
    return 0;
}
void dfs(int x)
{
    if(lc) dfs(lc);
    printf("%c",char(val[x]));
    if(rc) dfs(rc);
}

 

转载于:https://www.cnblogs.com/lxy8584099/p/10155361.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值