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

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

言归正传。

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

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

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

然后就没有然后了。

  map:array[..,'a'..'z']of longint;
t:array[..]of record
s:longint;
end;
root:array[..]of longint;
head,vet,next,dep:array[..]of longint;
f:array[..,..]of longint;
len:array[..]of string;
n,i,x,y,tot,tmp,cnt,j,k,q:longint;
zyd,ch1,ch:string; procedure add(a,b:longint;c:string);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
len[tot]:=c;
head[a]:=tot;
end; procedure dfs1(u:longint);
var e,v,i:longint;
begin
for i:= to do
begin
if dep[u]<(<<i) then break;
f[u,i]:=f[f[u,i-],i-];
end;
e:=head[u];
while e<> do
begin
v:=vet[e];
if v<>f[u,] then
begin
dep[v]:=dep[u]+;
f[v,]:=u;
dfs1(v);
end;
e:=next[e];
end;
end; procedure ins(var x:longint;i:longint);
begin
inc(cnt); t[cnt]:=t[x];
map[cnt]:=map[x];
x:=cnt; inc(t[x].s);
if i<=length(zyd) then ins(map[x,zyd[i]],i+);
end; function query(a,b,c,i:longint):longint;
begin
// writeln(a,' ',b,' ',c);
if i>length(zyd) then exit(t[a].s+t[b].s-t[c].s*);
exit(query(map[a,zyd[i]],map[b,zyd[i]],map[c,zyd[i]],i+));
end; procedure dfs2(u:longint);
var e,v:longint;
begin
e:=head[u];
while e<> do
begin
v:=vet[e];
if v<>f[u,] then
begin
root[v]:=root[u];
zyd:=len[e];
ins(root[v],);
dfs2(v);
end;
e:=next[e];
end;
end; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; function lca(x,y:longint):longint;
var i,d:longint;
begin
if dep[x]<dep[y] then swap(x,y);
d:=dep[x]-dep[y];
for i:= to do
if d and (<<i)> then x:=f[x,i];
for i:= downto do
if f[x,i]<>f[y,i] then
begin
x:=f[x,i]; y:=f[y,i];
end;
if x=y then exit(x);
exit(f[x,]);
end; begin
assign(input,'strings.in'); reset(input);
assign(output,'strings.out'); rewrite(output);
readln(n);
for i:= to n- do
begin
readln(ch);
j:=; x:=;
while (ch[j]>='')and(ch[j]<='') do
begin
x:=x*+ord(ch[j])-ord('');
inc(j);
end;
inc(j); y:=;
while (ch[j]>='')and(ch[j]<='') do
begin
y:=y*+ord(ch[j])-ord('');
inc(j);
end;
inc(j);
ch1:='';
for k:=j to length(ch) do ch1:=ch1+ch[k];
add(x,y,ch1);
add(y,x,ch1);
end; //f[1,0]:=1; dfs1();
dfs2();
readln(q);
for i:= to q do
begin
readln(ch);
j:=; x:=;
while (ch[j]>='')and(ch[j]<='') do
begin
x:=x*+ord(ch[j])-ord('');
inc(j);
end;
inc(j); y:=;
while (ch[j]>='')and(ch[j]<='') do
begin
y:=y*+ord(ch[j])-ord('');
inc(j);
end;
inc(j);
ch1:='';
for k:=j to length(ch) do ch1:=ch1+ch[k];
tmp:=lca(x,y);
zyd:=ch1;
writeln(query(root[x],root[y],root[tmp],));
end; close(input);
close(output);
end.

2016.12.25

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

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

如果是点则要-1

 var map:array[..,'a'..'z']of longint;
t:array[..]of longint;
root:array[..]of longint;
head,vet,next,dep,flag:array[..]of longint;
f:array[..,..]of longint;
len:array[..]of string;
n,i,x,y,tot,tmp,cnt,j,k,s,m,l,q:longint;
ch,h:string; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; procedure add(a,b:longint;c:string);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
len[tot]:=c;
head[a]:=tot;
end; function lca(x,y:longint):longint;
var d,i:longint;
begin
if dep[x]<dep[y] then swap(x,y);
d:=dep[x]-dep[y];
for i:= to do
if d and (<<i)> then x:=f[x,i];
for i:= downto do
if f[x,i]<>f[y,i] then
begin
x:=f[x,i]; y:=f[y,i];
end;
if x=y then exit(x);
exit(f[x,]);
end; procedure build(i:longint;var p:longint);
begin
inc(cnt); t[cnt]:=t[p];
map[cnt]:=map[p];
p:=cnt; inc(t[p]);
if i<=l then build(i+,map[p,h[i]]);
end; procedure dfs(u:longint);
var e,v,i:longint;
begin
for i:= to do
begin
if dep[u]<(<<i) then break;
f[u,i]:=f[f[u,i-],i-];
end;
flag[u]:=; e:=head[u];
while e<> do
begin
v:=vet[e];
if flag[v]= then
begin
dep[v]:=dep[u]+;
f[v,]:=u;
root[v]:=root[u];
h:=len[e]; l:=length(h);
build(,root[v]);
dfs(v);
end;
e:=next[e];
end;
end; function query(x,y,z,i:longint):longint;
begin
if i=l+ then exit(t[x]+t[y]-*t[z]);
exit(query(map[x,h[i]],map[y,h[i]],map[z,h[i]],i+));
end; begin
assign(input,'bzoj4477.in'); reset(input);
assign(output,'bzoj4477.out'); rewrite(output);
readln(n);
for i:= to n- do
begin
readln(ch);
k:=length(ch); x:=; y:=; h:='';
s:=;
for j:= to k do
begin
if ch[j]=' ' then begin inc(s); continue; end;
if s= then x:=x*+ord(ch[j])-ord('');
if s= then y:=y*+ord(ch[j])-ord('');
if s= then h:=h+ch[j];
end;
add(x,y,h);
add(y,x,h);
end;
dfs();
readln(m);
for i:= to m do
begin
readln(ch);
k:=length(ch); x:=; y:=; s:=; h:='';
for j:= to k do
begin
if ch[j]=' ' then begin inc(s); continue; end;
if s= then x:=x*+ord(ch[j])-ord('');
if s= then y:=y*+ord(ch[j])-ord('');
if s= then h:=h+ch[j];
end;
q:=lca(x,y);
l:=length(h);
writeln(query(root[x],root[y],root[q],));
end;
close(input);
close(output);
end.

【BZOJ4477】字符串树(可持久化Trie)的更多相关文章

  1. BZOJ4477[Jsoi2015]字符串树——可持久化trie树

    题目描述 萌萌买了一颗字符串树的种子,春天种下去以后夏天就能长出一棵很大的字符串树.字符串树很奇特,树枝上都密密麻麻写满了字符串,看上去很复杂的样子.[问题描述]字符串树本质上还是一棵树,即N个节点N ...

  2. luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树

    LINK:字符串树 先说比较简单的正解.由于我没有从最简单的考虑答案的角度思考 所以... 下次还需要把所有角度都考察到. 求x~y的答案 考虑 求x~根+y~根-2*lca~根的答案. 那么问题变成 ...

  3. [bzoj4477 Jsoi2015]字符串树 (可持久化trie)

    传送门 Solution 复习下tire( ̄▽ ̄)/ 裸的可持久化tire,我用树剖求了下LCA Code #include <cstdio> #include <cstring&g ...

  4. BZOJ 4477: [Jsoi2015]字符串树 可持久化trie树

    这个是真——可持久化字典树..... code: #include <bits/stdc++.h> #define N 100006 #define setIO(s) freopen(s& ...

  5. 4.24 省选模拟赛 欧珀瑞特 主席树 可持久化trie树

    很容易的一道题目.大概.不过我空间计算失误MLE了 我草草的计算了一下没想到GG了. 关键的是 我学了一个dalao的空间回收的方法 但是弄巧成拙了. 题目没有明确指出 在任意时刻数组长度为有限制什么 ...

  6. 【BZOJ-4212】神牛的养成计划 Trie树 + 可持久化Trie树

    4212: 神牛的养成计划 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 136  Solved: 27[Submit][Status][Discus ...

  7. 【BZOJ4212】神牛的养成计划 Trie树+可持久化Trie树

    [BZOJ4212]神牛的养成计划 Description Hzwer成功培育出神牛细胞,可最终培育出的生物体却让他大失所望...... 后来,他从某同校女神 牛处知道,原来他培育的细胞发生了基因突变 ...

  8. P4585-[FJOI2015]火星商店问题【线段树,可持久化Trie】

    正题 题目链接:https://www.luogu.com.cn/problem/P4585 题目大意 \(n\)个集合,开始每个集合中有一个数字. 开启新的一天并且往集合\(s\)中插入数字\(v\ ...

  9. BZOJ4477 JSOI2015字符串树(可持久化trie)

    树上建可持久化trie即可,有点过于裸了.darkbzoj过了然而在bzoj一直wa,不知道哪有锅. #include<iostream> #include<cstdio> # ...

  10. 【BZOJ4477】[JSOI2015]字符串树(Trie树)

    [BZOJ4477][JSOI2015]字符串树(Trie树) 题面 BZOJ 题解 对于每个点维护其到根节点的所有字符串构成的\(Trie\),显然可持久化一下就很好写了. 然后每次询问就是\(u+ ...

随机推荐

  1. NOIP2018 全国热身赛 第二场 (不开放)

    NOIP2018 全国热身赛 第二场 (不开放) 题目链接:http://noi.ac/contest/26/problem/60 一道蛮有趣的题目. 然后比赛傻逼了. 即将做出来的时候去做别的题了. ...

  2. 关于PHPExcel导出Excel时身份证,数字会导出为科学计数的处理方法

    上次在开发一个项目时,用到PHPExcel导出数据,其中有导出身份证等长串数字时导出的Excel中显示为科学计数方式. 这种显示很不人性化而且量多了修改起来也很麻烦. 这是因为Excel处理数字里默认 ...

  3. hihocoder#1098 : 最小生成树二·Kruscal算法

    #1098 : 最小生成树二·Kruscal算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 随着小Hi拥有城市数目的增加,在之间所使用的Prim算法已经无法继续使用 ...

  4. 笔记-python-装饰器

    笔记-python-装饰器 1.  装饰器 装饰器的实质是返回的函数对象的函数,其次返回的函数对象是可以调用的,搞清楚这两点后,装饰器是很容易理解的. 1.1.  相关概念理解 首先,要理解在Pyth ...

  5. python之返回状态commands模块

    需要得到命令执行的状态则需要判断$?的值, 在Python中有一个模块commands很容易做到以上的效果. commands.getstatusoutput(cmd)  返回一个元组(status, ...

  6. Diycode开源项目 SettingActivity分析

    1.整体效果预览及布局分析 1.1.设置界面预览 1.2.主体对应关系 注意这里的线条用ImageView来实现 有一个TextView是检查更新,默认隐藏,具体出现时间还得之后确认. 最后一个Lin ...

  7. 1022: [SHOI2008]小约翰的游戏John9(Auti_SG)

    1022: [SHOI2008]小约翰的游戏John Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3150  Solved: 2013[Submit] ...

  8. Python框架之Django学习笔记(三)

    开始一个项目 第一次使用 Django,必须进行一些初始化设置工作. 新建一个工作目录,例如 D:\tool\python\Python27\workspace\djcode,然后进入该目录. 转到创 ...

  9. MFC定时关机程序的实现2-添加启动项到注册表

    虽然上一篇实现了的定时关机,但是还不够完善,比如开机自动启动,然后按照配置的时间定时关机,并最小化到任务栏. 先来说开机启动怎么实现,开机启动实现的方法有好几种,比如直接在开始菜单启动项里添加一个程序 ...

  10. Python+Selenium框架设计篇之-什么是自动化测试框架

    1.什么是自动化测试框架 简单来说,自动化测试框架就是由一些标准,协议,规则组成,提供脚本运行的环境.自动化测试框架能够提供很多便利给用户高效完成一些事情,例如,结构清晰开发脚本,多种方式.平台执行脚 ...