题意:对原字符串插入若干字符后,动态查询某两个位置的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
;
}