pku2758 Checking the Text

 

题意:对原字符串插入若干字符后,动态查询某两个位置的lcp

RMQ用Square Table作O(nlogn)的预处理和O(1)的询问

#include <iostream>
#include 
<algorithm>
using namespace std;

#define MAXN 50010
#define Min(a,b) (a<b?a:b)

struct Ic{
    
int pos;
    
char ch;
}ic[
210];

int b[MAXN],array[4][MAXN],*sa,*nsa,*rank,*nrank,height[MAXN],n,m,M[MAXN][20],icnt;
char str[MAXN];

void make_sa(){
    
int i,k;

    sa
=array[0];
    nsa
=array[1];
    rank
=array[2];
    nrank
=array[3];

    memset(b,
0,sizeof(b));
    
for(i=0;i<n;i++)
        b[str[i]]
++;
    
for(i=1;i<=256;i++)
        b[i]
+=b[i-1];
    
for(i=n-1;i>=0;i--)
        sa[
--b[str[i]]]=i;

    
for(rank[sa[0]]=0,i=1;i<n;i++){
        rank[sa[i]]
=rank[sa[i-1]];
        
if(str[sa[i]]!=str[sa[i-1]])
            rank[sa[i]]
++;
    }

    
for(k=1;k<&& rank[sa[n-1]]<n-1;k*=2){
        
for(i=0;i<n;i++)
            b[rank[sa[i]]]
=i;
        
for(i=n-1;i>=0;i--)
            
if(sa[i]-k>=0)
                nsa[b[rank[sa[i]
-k]]--]=sa[i]-k;

        
for(i=n-k;i<n;i++)
            nsa[b[rank[i]]
--]=i;

        
for(nrank[nsa[0]]=0,i=1;i<n;i++){
            nrank[nsa[i]]
=nrank[nsa[i-1]];
            
if(rank[nsa[i]]!=rank[nsa[i-1]] || rank[nsa[i]+k]!=rank[nsa[i-1]+k])
                nrank[nsa[i]]
++;
        }

        
int *t=sa;sa=nsa;nsa=t;
        t
=rank;rank=nrank;nrank=t;
    }
}

void get_height(){
    
int i,j,k;
    
for(i=0,k=0;i<n;i++){
        
if(rank[i]==0)
            height[rank[i]]
=0;
        
else{
            
for(j=sa[rank[i]-1];str[i+k]==str[j+k];k++);
            height[rank[i]]
=k;
            
if(k>0)
                k
--;
        }
    }
}

void rmq_prepro(){/////////////////////////////////////////
    int i,j;
    
for(i=0;i<n;i++)
        M[i][
0]=i;
    
for(j=1;(1<<j)<=n;j++){
        
for(i=0;i+(1<<j)-1<n;i++){
            
if(height[M[i][j-1]]<height[M[i+(1<<(j-1))][j-1]])
                M[i][j]
=M[i][j-1];
            
else
                M[i][j]
=M[i+(1<<(j-1))][j-1];
        }
    }
}

void insert(char ch,int pos){
    
int i,j;
    
for(i=0;i<icnt;i++)
        
if(ic[i].pos>=pos)
            
break;
        
else
            pos
--;
    
for(j=icnt++;j>i;j--)
        ic[j]
=ic[j-1];
    
if(pos>n-1)
        pos
=n-1;
    ic[i].ch
=ch;
    ic[i].pos
=pos;
}
            

int lcp(int a,int b){////////////////////////////////////
    int k,t;
    a
=rank[a];
    b
=rank[b];
    
if(a>b)
        swap(a,b);
    a
++;//*
    t=b-a+1;
    
for(k=0;(1<<k)<=t;k++);k--;
    
return Min(height[M[a][k]],height[M[b-(1<<k)+1][k]]);
}

int mxlen(int a,int b){
    
int i,j,k,x,y,ret=0,t;
    
for(x=0;ic[x].pos<=a;x++);
    
for(y=0;ic[y].pos<=b;y++);
    
if(a==b)
        
return n-a+icnt-x-2;
    
while(1){
        k
=lcp(a,b);//////////////////////////////
        i=ic[x].pos-a;
        j
=ic[y].pos-b;
        t
=Min(k,Min(i,j));
        ret
+=t;a+=t;b+=t;
        
if(i==|| j==t){
            
while(ic[x].pos==&& ic[y].pos==b){
                
if(ic[x].ch==ic[y].ch){
                    x
++;y++;ret++;
                }
                
else
                    
return ret;
            }
            
while(ic[x].pos==a){
                
if(ic[x].ch==str[b]){
                    x
++;b++;ret++;
                }
                
else
                    
return ret;
            }
            
while(ic[y].pos==b){
                
if(ic[y].ch==str[a]){
                    y
++;a++;ret++;
                }
                
else
                    
return ret;
            }
        }
        
else
            
return ret;
    }
    
return ret;
}

    

    



int main(){
    
int i,j,t;
    
char order[3];
    
while(scanf("%s",str)!=EOF){
        scanf(
"%d",&m);
        n
=strlen(str);
        str[n
++]='#';
        str[n]
='\0';

        make_sa();
/////////
        get_height();////////
        rmq_prepro();////////

        ic[
0].ch='#';
        ic[
0].pos=MAXN;
        icnt
=1;

        
while(m--){
            scanf(
"%s",order);
            
if(order[0]=='I'){
                scanf(
"%s",order);
                scanf(
"%d",&t);
                t
--;
                insert(order[
0],t);
            }
            
else{
                scanf(
"%d%d",&i,&j);
                i
--;
                j
--;
                
if(i>j)
                    swap(i,j);
                printf(
"%d\n",mxlen(i,j));
            }
        }
    }
    
return 0;
}
posted @ 2008-11-24 01:09  Beetlebum  阅读(443)  评论(0编辑  收藏  举报