首页 > 代码库 > 【BZOJ4650&UOJ219】优秀的拆分(二分,hash)

【BZOJ4650&UOJ219】优秀的拆分(二分,hash)

题意:

技术分享

思路:

技术分享

 

技术分享

技术分享

 

在实现时SA可以用hash+二分代替,会多一个log

BZ上跑的飞快,但UOJ上extra卡出翔,已经放弃

不过转C或者写SA没准就过了

看来转C迫在眉睫

 1 const mo=700103;
 2 var f,g:array[0..100000]of int64;
 3     h,mi:array[0..100000]of int64;
 4     v,cas,i,n,j,x,y:longint;
 5     ans:int64;
 6     ch:ansistring;
 7  
 8 function min(x,y:longint):longint;
 9 begin
10  if x<y then exit(x);
11  exit(y);
12 end;
13  
14 function hash(x,y:longint):longint;
15 begin
16  hash:=(h[y]-h[x-1]*mi[y-x+1] mod mo+mo) mod mo;
17 end;
18  
19 function lcp(x,y:longint):longint;
20 var l,r,mid,last:longint;
21 begin
22  l:=1; r:=min(i,min(n-x+1,n-y+1)); last:=1;
23  while l<=r do
24  begin
25   mid:=(l+r)>>1;
26   if hash(x,x+mid-1)=hash(y,y+mid-1) then begin last:=mid; l:=mid+1; end
27    else r:=mid-1;
28  end;
29  exit(last);
30 end;
31  
32 function lcs(x,y:longint):longint;
33 var l,r,mid,last:longint;
34 begin
35  l:=1; r:=min(i,min(x,y)); last:=1;
36  while l<=r do
37  begin
38   mid:=(l+r)>>1;
39   if hash(x-mid+1,x)=hash(y-mid+1,y) then begin last:=mid; l:=mid+1; end
40    else r:=mid-1;
41  end;
42  exit(last);
43 end;
44  
45 begin
46  
47  mi[0]:=1;
48  for i:=1 to 50000 do mi[i]:=mi[i-1]*6662333 mod mo;
49  readln(cas);
50  for v:=1 to cas do
51  begin
52   readln(ch);
53   n:=length(ch);
54   for i:=0 to n+1 do
55   begin
56    f[i]:=0; g[i]:=0; h[i]:=0;
57   end;
58   for i:=1 to n do h[i]:=(h[i-1]*6662333+ord(ch[i])-ord(a)+1) mod mo;
59   for i:=1 to (n+1) div 2 do
60   begin
61    j:=1;
62    while j<=n do
63    begin
64     if j+i>n then break;
65     if (ch[j]<>ch[j+i]) then begin j:=j+i; continue; end;
66     x:=lcp(j,j+i); y:=lcs(j,j+i);
67    // x:=min(x,i); y:=min(y,i);
68     if x+y>i then
69     begin
70      inc(g[j-y+1]); dec(g[j+x-i+1]);
71      inc(f[j+i-y+i]); dec(f[j+i+x]);
72     end;
73     j:=j+i;
74    end;
75   end;
76   ans:=0;
77   for i:=1 to n do f[i]:=f[i-1]+f[i];
78   for i:=1 to n do g[i]:=g[i-1]+g[i];
79   for i:=1 to n-1 do ans:=ans+f[i]*g[i+1];
80   writeln(ans);
81  end;
82  
83 end.
84 

 

【BZOJ4650&UOJ219】优秀的拆分(二分,hash)