像这种“r相似”的题目是一种套路,搞出SA之后按height数组合并集合。
统计答案的时候注意细节
代码:
type
node=record
t,id:int64;
end;
const
maxn=300100;
maxl=-1000000000;
var
n,i,j,p,q:longint;
max,min,size:array[0..maxn]of int64;
s:ansistring;
a,rank,sa,x,y,buc,fa:array[0..maxn]of longint;
height,ans:array[0..maxn]of node;
procedure getsa(len:longint);
var
i,j,m,k,p:longint;
begin
m:=26;
for i:=1 to len do
begin
x[i]:=ord(s[i])-96;
inc(buc[x[i]]);
end;
for i:=2 to m do
buc[i]:=buc[i]+buc[i-1];
for i:=len downto 1 do
begin
sa[buc[x[i]]]:=i;
dec(buc[x[i]]);
end;
k:=1;
while k<=len do
begin
{for i:=1 to len do
write(sa[i],' ');
writeln; }
p:=0;
for i:=len downto len-k+1 do
begin
inc(p);
y[p]:=i;
end;
for i:=1 to len do
if sa[i]>k then
begin
inc(p);
y[p]:=sa[i]-k;
end;
fillchar(buc,sizeof(buc),0);
for i:=1 to len do
inc(buc[x[y[i]]]);
for i:=2 to m do
inc(buc[i],buc[i-1]);
for i:=len downto 1 do
begin
sa[buc[x[y[i]]]]:=y[i];
dec(buc[x[y[i]]]);
end;
for i:=1 to len do
y[i]:=x[i];
p:=1;
x[sa[1]]:=1;
for i:=2 to len do
if (y[sa[i]]=y[sa[i-1]])and(y[sa[i]+k]=y[sa[i-1]+k]) then x[sa[i]]:=p
else begin inc(p); x[sa[i]]:=p; end;
if p>=len then break;
m:=p;
k:=k*2;
end;
for i:=1 to len do
rank[sa[i]]:=i;
k:=0;
for i:=1 to len do
if rank[i]=1 then height[1].t:=0
else
begin
if k>0 then dec(k);
j:=sa[rank[i]-1];
while (s[i+k]=s[j+k])and(i+k<=len)and(j+k<=len) do inc(k);
height[rank[i]].t:=k;
end;
for i:=1 to len do
height[i].id:=i;
end;
procedure qs(p,q:longint);
var
i,j,mid:longint;
tt:node;
begin
i:=p;
j:=q;
mid:=height[(p+q)div 2].t;
repeat
while height[i].t>mid do inc(i);
while height[j].t<mid do dec(j);
if i<=j then
begin
tt:=height[i];
height[i]:=height[j];
height[j]:=tt;
inc(i);
dec(j)
end;
until i>j;
if p<j then qs(p,j);
if i<q then qs(i,q);
end;
procedure swap(var x,y:int64);
var
tt:longint;
begin
tt:=x;
x:=y;
y:=tt;
end;
function qmax(x,y:int64):int64;
begin
if x>y then exit(x)
else exit(y);
end;
function qmin(x,y:int64):int64;
begin
if x>y then exit(y)
else exit(x);
end;
function getfa(v:longint):longint;
begin
if fa[v]=v then exit(v);
fa[v]:=getfa(fa[v]);
exit(fa[v]);
end;
begin
readln(n);
readln(s);
for i:=1 to n do
read(a[i]);
if n=1 then begin writeln(0,' ',0); halt; end;
getsa(n);
qs(1,n);
height[n+1].t:=-1;
for i:=1 to n do
begin
fa[i]:=i;
size[i]:=1;
max[i]:=a[i];
min[i]:=a[i];
end;
for i:=n-1 downto height[1].t+1 do
begin
ans[i].t:=0;
ans[i].id:=0;
end;
for i:=height[1].t downto 0 do
begin
ans[i].t:=-maxl*maxl;
ans[i].id:=0;
end;
for i:=1 to n do
begin
if height[i].id=1 then continue;
p:=sa[height[i].id];
q:=sa[height[i].id-1];
if getfa(p)<>getfa(q) then
begin
ans[height[i].t].t:=qmax(ans[height[i].t].t,max[fa[p]]*max[fa[q]]);
ans[height[i].t].t:=qmax(ans[height[i].t].t,min[fa[p]]*min[fa[q]]);
ans[height[i].t].id:=ans[height[i].t].id+size[fa[q]]*size[fa[p]];
max[fa[q]]:=qmax(max[fa[q]],max[fa[p]]);
min[fa[q]]:=qmin(min[fa[q]],min[fa[p]]);
size[fa[q]]:=size[fa[q]]+size[fa[p]];
fa[getfa(p)]:=getfa(fa[q]);
end;
end;
for i:=height[1].t downto 0 do
begin
if i<>height[1].t then ans[i].t:=qmax(ans[i+1].t,ans[i].t);
ans[i].id:=ans[i+1].id+ans[i].id;
end;
for i:=0 to n-1 do
writeln(ans[i].id,' ',ans[i].t);
end.