您的位置:首页 > 其它

pku2758 Checking the Text

2008-11-24 01:09 316 查看
题意:对原字符串插入若干字符后,动态查询某两个位置的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<n && 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==t || j==t){

while(ic[x].pos==a && 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
='\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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: