zoukankan      html  css  js  c++  java
  • bzoj 1014 [JSOI2008]火星人prefix(splay+hash)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=1014

    【题意】

        给定一个字符串,要求提供修改一个字符,插入一个字符,查询两个后缀LCP的功能。

    【思路】

      splay维护字符串的哈希值。因为要提供区间,splay采用先查找后调整至根的写法。

        一个结点的hash值为:

            ch[0]->h * X^(ch[1]->s+1)+v * X^(ch[1]->s)+ch[1]->h

        对于一个询问每次二分长度,提取区间后比较hash值即可。

        需要注意的是splay要提前在区间的左右两边各加上一个节点,不然会调用到null。

        ull自然溢出相当于模2^64。

    【代码】

      1 #include<set>
      2 #include<cmath>
      3 #include<queue>
      4 #include<vector>
      5 #include<cstdio>
      6 #include<cstring>
      7 #include<iostream>
      8 #include<algorithm>
      9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
     10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     11 using namespace std;
     12 
     13 typedef long long ll;
     14 typedef unsigned long long ull;
     15 const int N = 5e5+10;
     16 const int X = 27;
     17 
     18 ll read() {
     19     char c=getchar();
     20     ll f=1,x=0;
     21     while(!isdigit(c)) {
     22         if(c=='-') f=-1; c=getchar();
     23     }
     24     while(isdigit(c))
     25         x=x*10+c-'0',c=getchar();
     26     return x*f;
     27 }
     28 
     29 char s[N];
     30 int n,q;
     31 ull powx[N];
     32 
     33 struct Node* null;
     34 struct Node {
     35     int s,v; ull h;
     36     Node* ch[2];
     37     int cmp(int k) {
     38         if(k==ch[0]->s+1) return -1;
     39         return k<=ch[0]->s? 0:1;
     40     }
     41     void init(int x) {
     42         v=h=x; s=1;
     43         ch[0]=ch[1]=null;
     44     }
     45     void maintain() {
     46         s=ch[0]->s+ch[1]->s+1;
     47         h=ch[0]->h*powx[ch[1]->s+1]+v*powx[ch[1]->s]+ch[1]->h;
     48     }
     49 } *root,nodepool[N]; int nodesz=0;
     50 
     51 void rot(Node* &o,int d) {
     52     Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o;
     53     o->maintain(),k->maintain(); o=k;
     54 }
     55 void splay(Node*& o,int k) {
     56     int d=o->cmp(k);
     57     if(d==1) k-=o->ch[0]->s+1;
     58     if(d!=-1) {
     59         Node* p=o->ch[d];
     60         int d2=p->cmp(k),k2=(d2==0?k:k-p->ch[0]->s-1);
     61         if(d2!=-1) {
     62             splay(p->ch[d2],k2);
     63             if(d==d2) rot(o,d^1); else rot(o->ch[d],d);
     64         }
     65         rot(o,d^1);
     66     }
     67 }
     68 //return range (l,r]
     69 //加过点后 s[l,r]=range(l,r+1)
     70 Node*& range(int l,int r) {
     71     splay(root,l);
     72     splay(root->ch[1],r-l+1);
     73     return root->ch[1]->ch[0];
     74 }
     75 
     76 Node* build(int l,int r)
     77 {
     78     if(r<l) return null;
     79     int mid=l+r>>1;
     80     Node* o=&nodepool[++nodesz];
     81     o->init(s[mid]-'a'+1);
     82     o->ch[0]=build(l,mid-1);
     83     o->ch[1]=build(mid+1,r);
     84     o->maintain();
     85     return o;
     86 }
     87 void insert(int p,int v) 
     88 {
     89     splay(root,p+1);
     90     Node* o=&nodepool[++nodesz]; 
     91     o->init(v);
     92     o->ch[0]=root->ch[0]; o->ch[1]=null;
     93     o->maintain();
     94     root->ch[0]=o; root->maintain();
     95 }
     96 void change(int p,int v)
     97 {
     98     splay(root,p);
     99     root->v=v;
    100     root->maintain();
    101 }
    102 
    103 int main()
    104 {
    105     //freopen("in.in","r",stdin);
    106     //freopen("out.out","w",stdout);
    107     null=new Node();
    108     scanf("%s",s+1);
    109     int n=strlen(s+1);
    110     s[0]='z'+1; s[++n]='z'+1; s[n+1]='';
    111     scanf("%d",&q);
    112     powx[0]=1;
    113     FOR(i,1,n+q) powx[i]=powx[i-1]*X;
    114     root=build(0,n);
    115     while(q--) {
    116         char op[2],val[2]; 
    117         int x,y;
    118         scanf("%s%d",op,&x);
    119         if(op[0]=='R') {
    120             scanf("%s",val);
    121             change(x+1,val[0]-'a'+1);
    122         } else 
    123         if(op[0]=='I') {
    124             scanf("%s",val);
    125             insert(x+1,val[0]-'a'+1);
    126         } else {
    127             scanf("%d",&y);
    128             int len=root->s,L=0,R=0;
    129             R=min(len-y-1,len-x-1);
    130             while(L<R) {
    131                 int M=L+(R-L+1)/2;
    132                 ull H=range(x,x+M)->h;
    133                 H-=range(y,y+M)->h;
    134                 if(!H) L=M; else R=M-1;
    135             }
    136             printf("%d
    ",L);
    137         }
    138         
    139     }
    140     return 0;
    141 }
  • 相关阅读:
    Machine-wide Progress Telerik Fiddler installation has been found at ...Please, use that one or uninstall it ...
    Jmeter接口测试(简单的)
    Loadrunner 访问数据库
    Windows MySQL查看log日志 同步log和系统时间
    Windows 修改MySQL配置文件my.ini后如何生效
    已打开Eclipse,但找不到Eclipse存放路径
    UiPath
    UiPath
    UiPath
    UiPath
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5297860.html
Copyright © 2011-2022 走看看