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