【BZOJ4477】字符串树(可持久化Trie)
此题花费我整整三天的功夫。还在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)的更多相关文章
- BZOJ4477[Jsoi2015]字符串树——可持久化trie树
题目描述 萌萌买了一颗字符串树的种子,春天种下去以后夏天就能长出一棵很大的字符串树.字符串树很奇特,树枝上都密密麻麻写满了字符串,看上去很复杂的样子.[问题描述]字符串树本质上还是一棵树,即N个节点N ...
- luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树
LINK:字符串树 先说比较简单的正解.由于我没有从最简单的考虑答案的角度思考 所以... 下次还需要把所有角度都考察到. 求x~y的答案 考虑 求x~根+y~根-2*lca~根的答案. 那么问题变成 ...
- [bzoj4477 Jsoi2015]字符串树 (可持久化trie)
传送门 Solution 复习下tire( ̄▽ ̄)/ 裸的可持久化tire,我用树剖求了下LCA Code #include <cstdio> #include <cstring&g ...
- BZOJ 4477: [Jsoi2015]字符串树 可持久化trie树
这个是真——可持久化字典树..... code: #include <bits/stdc++.h> #define N 100006 #define setIO(s) freopen(s& ...
- 4.24 省选模拟赛 欧珀瑞特 主席树 可持久化trie树
很容易的一道题目.大概.不过我空间计算失误MLE了 我草草的计算了一下没想到GG了. 关键的是 我学了一个dalao的空间回收的方法 但是弄巧成拙了. 题目没有明确指出 在任意时刻数组长度为有限制什么 ...
- 【BZOJ-4212】神牛的养成计划 Trie树 + 可持久化Trie树
4212: 神牛的养成计划 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 136 Solved: 27[Submit][Status][Discus ...
- 【BZOJ4212】神牛的养成计划 Trie树+可持久化Trie树
[BZOJ4212]神牛的养成计划 Description Hzwer成功培育出神牛细胞,可最终培育出的生物体却让他大失所望...... 后来,他从某同校女神 牛处知道,原来他培育的细胞发生了基因突变 ...
- P4585-[FJOI2015]火星商店问题【线段树,可持久化Trie】
正题 题目链接:https://www.luogu.com.cn/problem/P4585 题目大意 \(n\)个集合,开始每个集合中有一个数字. 开启新的一天并且往集合\(s\)中插入数字\(v\ ...
- BZOJ4477 JSOI2015字符串树(可持久化trie)
树上建可持久化trie即可,有点过于裸了.darkbzoj过了然而在bzoj一直wa,不知道哪有锅. #include<iostream> #include<cstdio> # ...
- 【BZOJ4477】[JSOI2015]字符串树(Trie树)
[BZOJ4477][JSOI2015]字符串树(Trie树) 题面 BZOJ 题解 对于每个点维护其到根节点的所有字符串构成的\(Trie\),显然可持久化一下就很好写了. 然后每次询问就是\(u+ ...
随机推荐
- 爬虫学习(三)——get请求参数解析
get请求: 用户输入搜索的内容,发送请求,将请求的内容保存起来. get请求的本质是在地址栏中输入参数进行的一种请求方式. 解析参数使用urllib.parse impo ...
- 二十九、MySQL 序列使用
MySQL 序列使用 MySQL 序列是一组整数:1, 2, 3, ...,由于一张数据表只能有一个字段自增主键, 如果你想实现其他字段也实现自动增加,就可以使用MySQL序列来实现. 本章我们将介绍 ...
- .pyc是什么鬼
.pyc是个什么鬼? 1. Python是一门解释型语言? 我初学Python时,听到的关于Python的第一句话就是,Python是一门解释性语言,我就这样一直相信下去,直到发现了*.pyc文件的存 ...
- 解决Uva网站打开慢的问题
https://blog.csdn.net/richenyunqi/article/details/80990535
- Kali 远程登陆SSH
一.配置SSH 编辑/etc/ssh/sshd_config 将#PasswordAuthentication no的注释去掉,将NO修改为YES //可以用密码登陆 将PermitRootLogin ...
- Js中的假值_ES5中定义的ToBoolean方法强制类型转换后值为false
你不知道的Javascript(中)--ToBoolean javascript中的值可以分为以下两类: 1.可以被强制类型转换为false的值 2.其他(被强制类型转换为true的值) 假值---以 ...
- Ntdsutil.exe
Ntdsutil.exe 编辑 本词条缺少名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! Ntdsutil.exe 是一个为 Active Directory 提供管理设施的命令行工具 ...
- 【palindrome partitioning II】cpp
题目: Given a string s, partition s such that every substring of the partition is a palindrome. Return ...
- 误删除pycharm项目中的文件,如何恢复?
如果写代码的时候,不小心删除来某个文件夹或者文件,而且删除后回收站也找不到, 可以使用如下方法恢复: 选择 Local History -> Show History : 选中需要reset到的 ...
- hnust 搬书
问题 G: 搬书 时间限制: 1 Sec 内存限制: 128 MB提交: 576 解决: 49[提交][状态][讨论版] 题目描述 XCQ队长要退役啦,由于队长常年刷题,机位上摆着各类算法书,一个 ...