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 ;
}

你可能感兴趣的:(check)