像這種“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.