bzoj 1014 LCP 二分 Hash 匹配

求同一字符串的两个后缀的最长公共前缀。

将字符串按位置放到Splay中维护(每个节点还维护一下该子树的hash),然后二分前缀的长度,用splay计算出指定范围的hash,按hash是否相等来判断是否相同。


 

  1 /**************************************************************
  2     Problem: 1014
  3     User: idy002
  4     Language: C++
  5     Result: Accepted
  6     Time:7188 ms
  7     Memory:4900 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <iostream>
 12 #include <cstring>
 13 #define maxn 100030
 14 using namespace std;
 15  
 16 typedef unsigned long long ulng;
 17  
 18 struct Splay {
 19     int pre[maxn], son[maxn][2], ch[maxn], siz[maxn], ntot, root;
 20     ulng hash[maxn];
 21     ulng power[maxn];
 22  
 23     int newnode( int p, int c ) {
 24         int nd = ++ntot;
 25         pre[nd] = p;
 26         son[nd][0] = son[nd][1] = 0;
 27         ch[nd] = c;
 28         siz[nd] = 1;
 29         hash[nd] = c;
 30         return nd;
 31     }
 32     void update( int nd ) {
 33         int ls = son[nd][0], rs = son[nd][1];
 34         siz[nd] = siz[ls]+siz[rs]+1;
 35         hash[nd] = hash[ls]*power[siz[rs]+1]+ch[nd]*power[siz[rs]]+hash[rs];
 36     }
 37     int build( int p, const char *str, int lf, int rg ) {   //  [lf,rg]
 38         if( lf>rg ) return 0;
 39         if( lf==rg ) return newnode(p,str[lf]-'a');
 40         int mid = (lf+rg)>>1;
 41         int nd = newnode( p, str[mid]-'a' );
 42         son[nd][0] = build( nd, str, lf, mid-1 );
 43         son[nd][1] = build( nd, str, mid+1, rg );
 44         update( nd );
 45         return nd;
 46     }
 47     void init( const char *str ) {
 48         root = ntot = 0;
 49         power[0] = 1ULL;
 50         for( int i=1; i<maxn; i++ )
 51             power[i] = power[i-1]*27ULL;
 52  
 53         root = newnode( 0, 'a'-'a' );
 54         int rnd = son[root][1] = newnode( root, 'a'-'a' );
 55         son[rnd][0] = build( rnd, str, 0, strlen(str)-1 );
 56         update( rnd );
 57         update( root );
 58     }
 59     void rotate( int nd, int d ) {
 60         int p = pre[nd];
 61         int s = son[nd][!d];
 62         int ss = son[s][d];
 63          
 64         son[nd][!d] = ss;
 65         son[s][d] = nd;
 66         if( p ) son[p][ nd==son[p][1] ] = s;
 67         else root = s;
 68  
 69         pre[s] = p;
 70         pre[nd] = s;
 71         if( ss ) pre[ss] = nd;
 72  
 73         update( nd );
 74         update( s );
 75     }
 76     void splay( int nd, int top=0 ) {
 77         while( pre[nd]!=top ) {
 78             int p = pre[nd];
 79             int nl = nd==son[p][0];
 80             if( pre[p]==top ) {
 81                 rotate( p, nl );
 82             } else {
 83                 int pp = pre[p];
 84                 int pl = p==son[pp][0];
 85                 if( nl==pl ) {
 86                     rotate( pp, pl );
 87                     rotate( p, nl );
 88                 } else {
 89                     rotate( p, nl );
 90                     rotate( pp, pl );
 91                 }
 92             }
 93         }
 94     }
 95     int find( int pos ) {
 96         int nd = root;
 97         while(1) {
 98             int ls = siz[son[nd][0]];
 99             if( nd==0 ) while(1);
100  
101             if( pos<=ls ) {
102                 nd = son[nd][0];
103             } else if( pos>=ls+2 ) {
104                 nd = son[nd][1];
105                 pos -= ls+1;
106             } else return nd;
107         }
108     }
109     void add_ch( int pos, int c ) {
110         int lnd = find(pos);
111         int rnd = find(pos+1);
112         splay(lnd);
113         splay(rnd,lnd);
114         son[rnd][0] = newnode( rnd, c );
115         splay( son[rnd][0] );
116     }
117     void chg_ch( int pos, int c ) {
118         int nd = find(pos);
119         ch[nd] = c;
120         update( nd );
121         splay( nd );
122     }
123     ulng qu_hash( int lf, int rg ) {
124         int lnd = find(lf-1);
125         int rnd = find(rg+1);
126         splay( lnd );
127         splay( rnd, lnd );
128         return hash[son[rnd][0]];
129     }
130     inline int size() { return siz[root]-2; }
131 };
132  
133 Splay T;
134 char str[maxn];
135 int m;
136  
137 int main() {
138     scanf( "%s", str );
139     T.init(str);
140     scanf( "%d", &m );
141     while(m--) {
142         char ch[10];
143         int pos, sa, sb;
144         scanf( "%s", ch );
145         if( ch[0]=='I' ) {
146             scanf( "%d%s", &pos, ch );
147             pos++;
148             T.add_ch( pos, ch[0]-'a' );
149         } else if( ch[0]=='R' ) {
150             scanf( "%d%s", &pos, ch );
151             pos++;
152             T.chg_ch( pos, ch[0]-'a' );
153         } else {
154             scanf( "%d%d", &sa, &sb );
155             sa++, sb++;
156             if( T.qu_hash(sa,sa) != T.qu_hash(sb,sb) ) {
157                 printf( "0
" );
158                 continue;
159             }
160             int len = T.size() - max(sa-1,sb-1) + 1;
161             int rl = 1, rr = len;
162             while( rl<rr ) {
163                 int md = (rl+rr+1)>>1;
164                 ulng ha = T.qu_hash( sa, sa+md-1 );
165                 ulng hb = T.qu_hash( sb, sb+md-1 );
166                 if( ha==hb ) rl = md;
167                 else rr = md-1;
168             }
169             printf( "%d
", rl );
170         }
171     }
172 }
173  
174 
View Code
原文地址:https://www.cnblogs.com/idy002/p/4296343.html