• 【BZOJ4477】字符串树(可持久化Trie)


    此题花费我整整三天的功夫。还在NoiP贴吧发过贴。

    最后发现trie树建新节点时信息未完全复制,真是愚蠢之极。

    言归正传。

    如果我们已经知道了每个点上的trie树那么询问就是sum[x]+sum[y]-sum[lca(x,y)]*2

    然后就是trie树变可持久化。

    DFS2中插入所有字符串,建立新节点,复制出现次数与trie树的next指针。

    然后就没有然后了。

      1  map:array[0..2100000,'a'..'z']of longint;
      2     t:array[0..2100000]of record
      3                            s:longint;
      4                           end;
      5     root:array[0..500000]of longint;
      6     head,vet,next,dep:array[1..500000]of longint;
      7     f:array[1..550000,0..18]of longint;
      8     len:array[1..500000]of string;
      9     n,i,x,y,tot,tmp,cnt,j,k,q:longint;
     10     zyd,ch1,ch:string;
     11 
     12 procedure add(a,b:longint;c:string);
     13 begin
     14  inc(tot);
     15  next[tot]:=head[a];
     16  vet[tot]:=b;
     17  len[tot]:=c;
     18  head[a]:=tot;
     19 end;
     20 
     21 procedure dfs1(u:longint);
     22 var e,v,i:longint;
     23 begin
     24  for i:=1 to 18 do
     25  begin
     26   if dep[u]<(1<<i) then break;
     27   f[u,i]:=f[f[u,i-1],i-1];
     28  end;
     29  e:=head[u];
     30  while e<>0 do
     31  begin
     32   v:=vet[e];
     33   if v<>f[u,0] then
     34   begin
     35    dep[v]:=dep[u]+1;
     36    f[v,0]:=u;
     37    dfs1(v);
     38   end;
     39   e:=next[e];
     40  end;
     41 end;
     42 
     43 procedure ins(var x:longint;i:longint);
     44 begin
     45  inc(cnt); t[cnt]:=t[x];
     46  map[cnt]:=map[x];
     47  x:=cnt; inc(t[x].s);
     48  if i<=length(zyd) then ins(map[x,zyd[i]],i+1);
     49 end;
     50 
     51 function query(a,b,c,i:longint):longint;
     52 begin
     53 // writeln(a,' ',b,' ',c);
     54  if i>length(zyd) then exit(t[a].s+t[b].s-t[c].s*2);
     55  exit(query(map[a,zyd[i]],map[b,zyd[i]],map[c,zyd[i]],i+1));
     56 end;
     57 
     58 procedure dfs2(u:longint);
     59 var e,v:longint;
     60 begin
     61  e:=head[u];
     62  while e<>0 do
     63  begin
     64   v:=vet[e];
     65   if v<>f[u,0] then
     66   begin
     67    root[v]:=root[u];
     68    zyd:=len[e];
     69    ins(root[v],1);
     70    dfs2(v);
     71   end;
     72   e:=next[e];
     73  end;
     74 end;
     75 
     76 procedure swap(var x,y:longint);
     77 var t:longint;
     78 begin
     79  t:=x; x:=y; y:=t;
     80 end;
     81 
     82 function lca(x,y:longint):longint;
     83 var i,d:longint;
     84 begin
     85  if dep[x]<dep[y] then swap(x,y);
     86  d:=dep[x]-dep[y];
     87  for i:=0 to 18 do
     88   if d and (1<<i)>0 then x:=f[x,i];
     89  for i:=18 downto 0 do
     90   if f[x,i]<>f[y,i] then
     91   begin
     92    x:=f[x,i]; y:=f[y,i];
     93   end;
     94  if x=y then exit(x);
     95  exit(f[x,0]);
     96 end;
     97 
     98 begin
     99  assign(input,'strings.in'); reset(input);
    100  assign(output,'strings.out'); rewrite(output);
    101  readln(n);
    102  for i:=1 to n-1 do
    103  begin
    104   readln(ch);
    105   j:=1; x:=0;
    106   while (ch[j]>='0')and(ch[j]<='9') do
    107   begin
    108    x:=x*10+ord(ch[j])-ord('0');
    109    inc(j);
    110   end;
    111   inc(j); y:=0;
    112   while (ch[j]>='0')and(ch[j]<='9') do
    113   begin
    114    y:=y*10+ord(ch[j])-ord('0');
    115    inc(j);
    116   end;
    117   inc(j);
    118   ch1:='';
    119   for k:=j to length(ch) do ch1:=ch1+ch[k];
    120   add(x,y,ch1);
    121   add(y,x,ch1);
    122  end;
    123 
    124  //f[1,0]:=1;
    125 
    126  dfs1(1);
    127  dfs2(1);
    128  readln(q);
    129  for i:=1 to q do
    130  begin
    131   readln(ch);
    132   j:=1; x:=0;
    133   while (ch[j]>='0')and(ch[j]<='9') do
    134   begin
    135    x:=x*10+ord(ch[j])-ord('0');
    136    inc(j);
    137   end;
    138   inc(j); y:=0;
    139   while (ch[j]>='0')and(ch[j]<='9') do
    140   begin
    141    y:=y*10+ord(ch[j])-ord('0');
    142    inc(j);
    143   end;
    144   inc(j);
    145   ch1:='';
    146   for k:=j to length(ch) do ch1:=ch1+ch[k];
    147   tmp:=lca(x,y);
    148   zyd:=ch1;
    149   writeln(query(root[x],root[y],root[tmp],1));
    150  end;
    151 
    152  close(input);
    153  close(output);
    154 end.
    View Code

     2016.12.25

    学会主席树后重写了一遍,感觉异常轻松

    因为此题询问的是边上的信息,所以LCA点不会被重复计算,询问时也就不用-1

    如果是点则要-1

      1 var map:array[0..2100000,'a'..'z']of longint;
      2     t:array[0..2100000]of longint;
      3     root:array[1..500000]of longint;
      4     head,vet,next,dep,flag:array[1..500000]of longint;
      5     f:array[1..550000,0..18]of longint;
      6     len:array[1..500000]of string;
      7     n,i,x,y,tot,tmp,cnt,j,k,s,m,l,q:longint;
      8     ch,h:string;
      9 
     10 
     11 procedure swap(var x,y:longint);
     12 var t:longint;
     13 begin
     14  t:=x; x:=y; y:=t;
     15 end;
     16 
     17 procedure add(a,b:longint;c:string);
     18 begin
     19  inc(tot);
     20  next[tot]:=head[a];
     21  vet[tot]:=b;
     22  len[tot]:=c;
     23  head[a]:=tot;
     24 end;
     25 
     26 function lca(x,y:longint):longint;
     27 var d,i:longint;
     28 begin
     29  if dep[x]<dep[y] then swap(x,y);
     30  d:=dep[x]-dep[y];
     31  for i:=0 to 18 do
     32   if d and (1<<i)>0 then x:=f[x,i];
     33  for i:=18 downto 0 do
     34   if f[x,i]<>f[y,i] then
     35   begin
     36    x:=f[x,i]; y:=f[y,i];
     37   end;
     38  if x=y then exit(x);
     39  exit(f[x,0]);
     40 end;
     41 
     42 procedure build(i:longint;var p:longint);
     43 begin
     44  inc(cnt); t[cnt]:=t[p];
     45  map[cnt]:=map[p];
     46  p:=cnt; inc(t[p]);
     47  if i<=l then build(i+1,map[p,h[i]]);
     48 end;
     49 
     50 procedure dfs(u:longint);
     51 var e,v,i:longint;
     52 begin
     53  for i:=1 to 18 do
     54  begin
     55   if dep[u]<(1<<i) then break;
     56   f[u,i]:=f[f[u,i-1],i-1];
     57  end;
     58  flag[u]:=1; e:=head[u];
     59  while e<>0 do
     60  begin
     61   v:=vet[e];
     62   if flag[v]=0 then
     63   begin
     64    dep[v]:=dep[u]+1;
     65    f[v,0]:=u;
     66    root[v]:=root[u];
     67    h:=len[e]; l:=length(h);
     68    build(1,root[v]);
     69    dfs(v);
     70   end;
     71   e:=next[e];
     72  end;
     73 end;
     74 
     75 function query(x,y,z,i:longint):longint;
     76 begin
     77  if i=l+1 then exit(t[x]+t[y]-2*t[z]);
     78  exit(query(map[x,h[i]],map[y,h[i]],map[z,h[i]],i+1));
     79 end;
     80 
     81 begin
     82  assign(input,'bzoj4477.in'); reset(input);
     83  assign(output,'bzoj4477.out'); rewrite(output);
     84  readln(n);
     85  for i:=1 to n-1 do
     86  begin
     87   readln(ch);
     88   k:=length(ch); x:=0; y:=0; h:='';
     89   s:=1;
     90   for j:=1 to k do
     91   begin
     92    if ch[j]=' ' then begin inc(s); continue; end;
     93    if s=1 then x:=x*10+ord(ch[j])-ord('0');
     94    if s=2 then y:=y*10+ord(ch[j])-ord('0');
     95    if s=3 then h:=h+ch[j];
     96   end;
     97   add(x,y,h);
     98   add(y,x,h);
     99  end;
    100  dfs(1);
    101  readln(m);
    102  for i:=1 to m do
    103  begin
    104   readln(ch);
    105   k:=length(ch); x:=0; y:=0; s:=1; h:='';
    106   for j:=1 to k do
    107   begin
    108    if ch[j]=' ' then begin inc(s); continue; end;
    109    if s=1 then x:=x*10+ord(ch[j])-ord('0');
    110    if s=2 then y:=y*10+ord(ch[j])-ord('0');
    111    if s=3 then h:=h+ch[j];
    112   end;
    113   q:=lca(x,y);
    114   l:=length(h);
    115   writeln(query(root[x],root[y],root[q],1));
    116  end;
    117  close(input);
    118  close(output);
    119 end.
    null
  • 相关阅读:
    效能分析
    四人小组项目--连连看的设计与实现
    每周工作量及进度统计(第三周)
    四则运算改进版
    词频统计改进版1
    SCRUM站立会议
    四则运算
    效能分析
    四人小组项目的需求和功能等描述
    通读构建之法
  • 原文地址:https://www.cnblogs.com/myx12345/p/5017497.html
Copyright © 2020-2023  润新知