Jewel Magic UVA

2018-02-28 07:45:46来源:cnblogs.com作者:11996 - hehe_54321人点击

分享
第七城市

Jewel Magic UVA - 11996

这是一道用splay/非旋treap做的题(这里用的是非旋treap)

1/2/3是splay/非旋treap的常规操作。对于操作4,可以用哈希法求LCP。记hash(i,L)为子串[i,i+L-1](即第i个开始的L个)的hash值。记s[i]为序列第i位(编号从1开始),n为序列长度

如果通过某种方式做到能在O(logn)时间内取出一段子串的hash值,那么二分答案(即LCP长度x),可以在O(logn)时间内判一个x是否合法(如果hash(l,x)==hash(r,x)则认为[l,l+x-1]和[r,r+x-1]是相同的,合法,否则不合法),可以做到在O(log^2n)内完成一个操作4。当然,hash判字符串是否相同正确性可能受影响,因此可以多计算一些hash,当他们都相同时才认为字符串相同,可以将错误率降到足够小。

如何维护一段子串的hash值?首先定义x为任意整数,定义$hash(i,L)=s[i+L-1]*x^{L-1}+s[i+L-2]*x^{L-2}+...+s[i+1]*x+s[i]$

(这里及之后都省略了取模)

(简单记法:左边乘的次数小)

(另一种记法:另一种求法的伪代码表示:ans=0;for(j=i+L-1;j>=i;j--)  ans=ans*x+s[j];)

可以发现:如果已知hash(i,p)和hash(i+p,q)(即已知[i,i+p-1]和[i+p,i+p+q-1]的hash值),要求hash(i,p+q)(就是这两段合起来的hash值),那么:

令j=i+p,那么$hash(i,p+q)$

$=s[j+q-1]*x^{p+q-1}+s[j+q-2]*x^{p+q-2}+...+s[j]*x^p+s[i+p-1]*x^{p-1}+...+s[i]*x^0$

所以$hash(i,p+q)=hash(j,q)*x^p+hash(i,p)=hash(i,p)+hash(i+p,q)*x^p$

这样就得到了对于平衡树某个节点,根据子节点为根的子树的hash值与自身值求以自身为根的子树的hash值的方法(先将左子树和自身合起来,再将结果与右子树合起来)

当然,由于此题有一个翻转操作,对于一个节点要维护两个hash:正向序列hash和反向序列hash。翻转操作时顺便交换一下两个的值。

附:这道题没有卡hash,单hash就能过,

附:听说操作4有O(logn)的方法?待解决

错误记录:

1.141行误用build函数(build是用的左闭右闭区间),输入了(a+1,a+n+1)。(然而不知道为什么虽然过不了udebug的数据然而把题目A掉了)

2.没注意在字符前还是字符后插入

*3.posib函数写错:没有考虑要计算hash值的串超出长度范围的情况(就是第二个"&&"之前的部分)。错了不止一次

4.可能出现的错误:如果hash不用ull自然溢出,自己取模,那么要考虑爆int、爆longlong、负数等等

  1 #include<cstdio>  2 #include<algorithm>  3 using namespace std;  4 inline int rand1()  5 {  6     static int x=471;  7     return x=(48271LL*x+1)%2147483647;  8 }  9 unsigned long long powx[400010]; 10 struct Node 11 { 12     Node(){} 13     Node* ch[2]; 14     int r; 15     bool flip; 16     int v; 17     unsigned long long h,rh; 18     int size; 19     void upd() 20     { 21         if(ch[0])   ch[0]->pd(); 22         if(ch[1])   ch[1]->pd(); 23         size=1+(ch[0]?ch[0]->size:0)+(ch[1]?ch[1]->size:0); 24         h=(ch[0]?ch[0]->h:0)+v*powx[ch[0]?ch[0]->size:0]+(ch[1]?ch[1]->h:0)*powx[(ch[0]?ch[0]->size:0)+1]; 25         rh=(ch[1]?ch[1]->rh:0)+v*powx[ch[1]?ch[1]->size:0]+(ch[0]?ch[0]->rh:0)*powx[(ch[1]?ch[1]->size:0)+1]; 26     } 27     void pd() 28     { 29         if(flip) 30         { 31             swap(ch[0],ch[1]); 32             swap(h,rh); 33             if(ch[0])   (ch[0]->flip)^=1; 34             if(ch[1])   (ch[1]->flip)^=1; 35             flip=0; 36         } 37     } 38 }nodes[400010]; 39 Node* root;int mem; 40 Node* getnode(){return nodes+(mem++);} 41 Node* merge(Node* a,Node* b) 42 { 43     if(a==NULL)    return b; 44     if(b==NULL)    return a; 45     if(a->r < b->r) 46     { 47         a->pd();a->ch[1]=merge(a->ch[1],b);a->upd(); 48         return a; 49     } 50     else 51     { 52         b->pd();b->ch[0]=merge(a,b->ch[0]);b->upd(); 53         return b; 54     } 55 } 56 typedef pair<Node*,Node*> P; 57 P split(Node* a,int n) 58 { 59     if(a==NULL)    return P(NULL,NULL); 60     P y; 61     a->pd();int s=a->ch[0] ? a->ch[0]->size : 0; 62     if(s>=n) 63     { 64         y=split(a->ch[0],n); 65         a->ch[0]=y.second;a->upd(); 66         y.second=a; 67     } 68     else 69     { 70         y=split(a->ch[1],n-s-1); 71         a->ch[1]=y.first;a->upd(); 72         y.first=a; 73     } 74     return y; 75 } 76 inline void insert(int k,int x) 77 { 78     Node* t=getnode(); 79     t->ch[0]=t->ch[1]=NULL;t->r=rand1();t->v=x;t->flip=0;t->upd(); 80     P y=split(root,k-1); 81     root=merge(merge(y.first,t),y.second); 82 } 83 inline void erase(int k) 84 { 85     P y=split(root,k-1); 86     P y2=split(y.second,1); 87     root=merge(y.first,y2.second); 88 } 89 inline void reverse(int l,int r) 90 { 91     if(l>r) swap(l,r); 92     P y=split(root,l-1); 93     P y2=split(y.second,r-l+1); 94     y2.first->flip^=1; 95     root=merge(merge(y.first,y2.first),y2.second); 96 } 97 inline int size() 98 { 99     return root ? root->size : 0;100 }101 inline unsigned long long geth(int l,int r)102 {103     if(l>r)  return 0;104     P y=split(root,l-1);105     P y2=split(y.second,r-l+1);106     unsigned long long ans=y2.first ? y2.first->h : 0;107     root=merge(merge(y.first,y2.first),y2.second);108     return ans;109 }110 Node* build(int *l,int *r)111 {112     if(l>r) return NULL;113     if(l==r)114     {115         Node* t=getnode();116         t->ch[0]=t->ch[1]=NULL;t->r=rand1();t->v=*l;t->flip=0;t->upd();117         return t;118     }119     else120     {121         int* mid=l+(r-l)/2;122         return merge(build(l,mid),build(mid+1,r));123     }124 }125 int n,m,q;126 int a[200010];127 const int X=127;128 int l,r;129 inline bool posib(int x)130 {131     return (l+x-1<=size())&&(r+x-1<=size())&&(geth(l,l+x-1)==geth(r,r+x-1));132 }133 int main()134 {135     register int i;136     int lx,rx,k,x,mid,tmp;137     powx[0]=1;138     for(i=1;i<=400000;i++)  powx[i]=powx[i-1]*X;139     scanf("%d%d",&n,&q);140     for(i=1;i<=n;i++)    scanf("%1d",&a[i]);141     root=build(a+1,a+n);142     while(q--)143     {144         scanf("%d",&tmp);145         if(tmp==1)146         {147             scanf("%d%d",&k,&x);148             insert(k+1,x);149         }150         else if(tmp==2)151         {152             scanf("%d",&k);153             erase(k);154         }155         else if(tmp==3)156         {157             scanf("%d%d",&l,&r);158             reverse(l,r);159         }160         else if(tmp==4)161         {162             scanf("%d%d",&l,&r);163             lx=0;rx=size()+1;164             while(rx-lx>1)165             {166                 mid=(lx+rx)>>1;167                 if(posib(mid))  lx=mid;168                 else    rx=mid;169             }170             printf("%d/n",lx);171         }172     }173     return 0;174 }
第七城市

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台