题目
Description
新日暮里中,比冲是一位博学的哲学教授。由于最近要帮学生准备考试,他决定弄个提纲给学生。然而同事van不服气,觉得这样学生就没有了自我思考,便在提纲中添加废话。
比冲很无奈,他想找回原稿。我们把现在的提纲看成是一个字符串S。他知道van只会在原稿结尾添加语句,也就是说,原稿是S的前缀。
现在比冲有m个询问,以此来找出原稿。每次给出两个位置l,r,问以l与r结尾的字符串中,有多少个字符串符合原稿的性质,最长的有多长。
Input
第一行一个只包含小写字母的字符串S,代表被改过的提纲。注意字符串从1开始编号。
第二行一个正整数m,即询问数。
接下来m行,每行两个正整数l,r,即位置。
Output
共m行,每行两个正整数a,b,a表示有多少个合法字符串,b为最长合法字符串长度。
Sample Input
输入1:
nguangdongren
2
5 13
6 10
输入2:
ababbaabbaababab
3
14 16
3 6
2 4
Sample Output
输出1:
1 1
1 2
输出2:
2 4
1 1
1 2
Data Constraint
30%:|S|<=300;m<=300
60%: |S|<=3000;m<=100000
100%:|S|<=30000;m<=100000
当我打这一题的题解时已经快要下课啦,为了不影响我的腐败宿舍生活,我决定很无耻的随便随便乱扯两句草草了事23333,我们处理出kmp中的fail数组,设fail[i]为i
的父亲,根节点的深度为零,用这样的方法建立一棵tree,对于每次的查询x,y我们用倍增找到他们的lca,然后输出他们lca的深度以及lca的位置就可以了。
贴代码(我感觉我的倍增打的好丑啊2333)
var
deep,next:array[0..30005]of longint;
f:array[0..30005,0..20]of longint;
bz:array[0..30005]of boolean;
s:ansistring;
i,j,k,l,n,x,y,len,p:longint;
procedure dfs(x:longint);
begin
if deep[next[x]]=0 then dfs(next[x]);
deep[x]:=deep[next[x]]+1;
end;
procedure kmp;
begin
readln(s);
len:=length(s);
for i:=2 to len do
begin
while (j>0) and (s[j+1]<>s[i]) do j:=next[j];
if s[j+1]=s[i] then inc(j);
next[i]:=j;
bz[j]:=true;
f[i,0]:=j;
end;
end;
procedure makefather;
begin
for j:=1 to p do
for i:=1 to len do
f[i,j]:=f[f[i,j-1],j-1];
end;
begin
kmp;
deep[0]:=1;
for i:=2 to len do if bz[i]=false then dfs(i);
i:=1;
p:=0;
while i<len do
begin
i:=i*2;
inc(p);
end;
if i>len then dec(p);
makefather;
readln(n);
for i:=1 to n do
begin
readln(x,y);
if deep[x]<deep[y] then
begin
l:=x;
x:=y;
y:=l;
end;
l:=deep[x]-deep[y];
j:=1;
k:=0;
while l>0 do
begin
if l and 1=1 then x:=f[x,k];
inc(k);
j:=j*2;
l:=l div 2;
end;
k:=0;
j:=1;
while j<deep[x] do
begin
j:=j*2;
inc(k);
end;
if j>deep[x] then dec(k);
for j:=k downto 0 do
if f[x,j]<>f[y,j] then
begin
x:=f[x,j];
y:=f[y,j];
end;
if x<>y then x:=f[x,0];
writeln(deep[x]-1,' ',x);
end;
end.