• BZOJ3998:[TJOI2015]弦论


    Description

    对于一个给定长度为N的字符串,求它的第K小子串是什么。

    Input

     第一行是一个仅由小写英文字母构成的字符串S

    第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个。T=1则表示不同位置的相同子串算作多个。K的意义如题所述。

    Output

    输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1

    Sample Input

    aabc
    0 3

    Sample Output

    aab

    HINT

    N<=5*10^5

    T<2

    K<=10^9

    题解:

    原本想写后缀数组的,但到网上搜了一下发现用后缀数组会TLE,于是便学习了后缀自动机。

    关于后缀自动机请orz大神犇

    在这道题中,t有两种情况。

    对于t=0的情况,每个后缀节点的size为1,记忆化dfs一遍即可。

    对于t=1的情况,先把整个字符串输入自动机,将沿途经过的点的初始size赋为1,其余节点赋为0(表示字符串是原串的前缀的情况);

    然后沿pre树进行一次dfs,将节点的最终size赋为其pre子树的初始size之和(因为该节点是这些节点的后缀)。

    随后像第一种情况一样进行记忆化dfs。

    代码:

     1 var
     2   i,j,l,n,m,now,last,t,cnt:longint;
     3   k:int64;
     4   a:array[0..1000005,'a'..'z']of int64;
     5   pre,v,step,c:array[0..1000005]of longint;
     6   size,size2:array[0..1000005]of int64;
     7   b:array[0..1000005,1..2]of longint;
     8   s:ansistring;
     9   ch:char;
    10 function ss(x:longint):int64;
    11 var i:longint;
    12 begin
    13   i:=c[x];
    14   while i>0 do begin size[x]:=size[x]+ss(b[i,1]); i:=b[i,2]; end;
    15   exit(size[x]);
    16 end;
    17 procedure ss2(x:longint);
    18 var i:char;
    19 begin
    20   if v[x]=1 then exit;
    21   v[x]:=1;
    22   for i:='a' to 'z' do
    23   begin
    24     if a[x,i]>0 then
    25     begin ss2(a[x,i]); size2[x]:=size2[x]+size2[a[x,i]]; end;
    26   end;
    27   size2[x]:=size2[x]+size[x];
    28 end;
    29 procedure qq(x:longint);
    30 var i:char;
    31 begin
    32   k:=k-size[x]; if k<=0 then exit;
    33   for i:='a' to 'z' do
    34   begin
    35     if(a[x,i]>0)and(k-size2[a[x,i]]<=0)then
    36     begin write(i); qq(a[x,i]); break; end;
    37     if a[x,i]>0 then k:=k-size2[a[x,i]];
    38   end;
    39 end;
    40 begin
    41   readln(s);
    42   readln(t,k); pre[0]:=-1;
    43   for i:=1 to length(s) do
    44   begin
    45     inc(m); now:=m; step[now]:=step[last]+1; size[now]:=1;
    46     while(last<>-1)and(a[last,s[i]]=0)do
    47     begin a[last,s[i]]:=now; last:=pre[last]; end;
    48     if last=-1 then begin pre[now]:=0; last:=now; continue; end;
    49     if step[last]+1=step[a[last,s[i]]] then
    50     begin pre[now]:=a[last,s[i]]; last:=now; continue; end;
    51     j:=a[last,s[i]];
    52     inc(m); a[m]:=a[j]; pre[m]:=pre[j]; step[m]:=step[last]+1;
    53     pre[j]:=m; pre[now]:=m;
    54     while last<>-1 do
    55     begin
    56       if a[last,s[i]]=j then a[last,s[i]]:=m else break;
    57       last:=pre[last];
    58     end;
    59     last:=now;
    60   end;
    61   for i:=1 to m do
    62   begin inc(cnt); b[cnt,1]:=i; b[cnt,2]:=c[pre[i]]; c[pre[i]]:=cnt; end;
    63   if t=1 then ss(0) else
    64   for i:=1 to m do size[i]:=1;
    65   size[0]:=0;
    66   ss2(0);
    67   if size2[0]<k then writeln(-1)else begin qq(0); writeln; end;
    68 end.
    View Code
  • 相关阅读:
    go context
    go etcd
    go logs
    go config
    go tail
    kafka与zookeeper
    go kafka
    go mysql
    array_map array_walk
    单独配置的nginx mysql 重启
  • 原文地址:https://www.cnblogs.com/GhostReach/p/6292255.html
Copyright © 2020-2023  润新知