BZOJ.4212.神牛的养成计划(Trie 可持久化Trie)
为啥hzw的题也是权限题啊
考虑能够匹配\(s1\)这一前缀的串有哪些性质。对所有串排序,能发现可以匹配\(s1\)的是一段区间,可以建一棵\(Trie\)求出来,设为\([l,r]\)。
同理匹配\(s2\)这一后缀的也是一段区间,就可以二维数点了。
然后要求的就是\([l,r]\)中的串匹配\(s2\)的有多少个。把所有串reverse,建一棵可持久化\(Trie\),在上面匹配就可以了。
排序的时候可以不用sort,可以直接在第一棵\(Trie\)上DFS。这样虽然省个\(\log\)但这题\(n\)才\(2000\),那个不用边表还有\(26\)的常数=-=。所以直接sort比较的时候暴力一位一位比好了。参考了下\(clover\_hxy\)的写法。
复杂度\(O(26n)\)。排序复杂度最坏\(O(n|s_i|\log n)\)然而根本到不了。
如果不强制在线,直接离线暴力对集合求交复杂度是线性的吧?
//439336kb 2988ms
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define MAXIN 1000000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=2e6+5,M=2005;
int A[N],L[M],R[M],id[M],root[M];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Trie
{
int tot,son[N][26],L[N],R[N];
void Insert(int *s,int *ed,int id)
{
for(int x=0; s!=ed; ++s)
{
x=son[x][*s]?son[x][*s]:(L[++tot]=N,son[x][*s]=tot);
L[x]=std::min(L[x],id), R[x]=std::max(R[x],id);
}
}
void Query(int *s,int *ed,int &l,int &r)
{
int x=0;
for(; s!=ed; ++s)
if(son[x][*s]) x=son[x][*s];
else {l=-1; return;}
l=L[x], r=R[x];
}
}T1;
struct Trie2
{
int tot,son[N][26],sz[N];
void Insert(int *s,int *ed,int &rt,int y)//reverse
{
for(int x=rt=++tot; s!=ed; --s)
{
memcpy(son[x],son[y],sizeof son[y]);
x=son[x][*s]=++tot, y=son[y][*s], sz[x]=sz[y]+1;
}
}
int Query(int *s,int *ed,int x,int y)//y-x
{
for(; s!=ed; --s)
if(sz[son[y][*s]]-sz[son[x][*s]]>0) x=son[x][*s], y=son[y][*s];
else return 0;
return sz[y]-sz[x];
}
}T2;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline bool cmp(int a,int b)
{
int p1=L[a],p2=L[b],l=std::min(R[a]-p1,R[b]-p2);
for(int i=0; i<=l; ++i) if(A[p1+i]!=A[p2+i]) return A[p1+i]<A[p2+i];
return R[a]-p1<R[b]-p2;
}
int main()
{
int n=read(),tot=0;
for(int i=1; i<=n; ++i)
{
L[i]=tot+1;
register char c; while(!isalpha(c=gc()));
for(; isalpha(c); A[++tot]=c-97,c=gc());
R[i]=tot, id[i]=i;
}
std::sort(id+1,id+1+n,cmp);
for(int i=1; i<=n; ++i) T1.Insert(A+L[id[i]],A+R[id[i]]+1,i);
for(int i=1; i<=n; ++i) T2.Insert(A+R[id[i]],A+L[id[i]]-1,root[i],root[i-1]);
for(int Q=read(),ans=0; Q--; )
{
register char c; while(!isalpha(c=gc()));
int cnt=0;
for(; isalpha(c); A[++cnt]=(c-97+ans)%26,c=gc());
int tmp=cnt; while(!isalpha(c=gc()));
for(; isalpha(c); A[++cnt]=(c-97+ans)%26,c=gc());
int l,r; T1.Query(A+1,A+tmp+1,l,r);
if(l!=-1) printf("%d\n",ans=T2.Query(A+cnt,A+tmp,root[l-1],root[r]));
else printf("%d\n",ans=0);
}
return 0;
}
BZOJ.4212.神牛的养成计划(Trie 可持久化Trie)的更多相关文章
- BZOJ 4212: 神牛的养成计划
4212: 神牛的养成计划 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 142 Solved: 30[Submit][Status][Discus ...
- BZOJ 4212: 神牛的养成计划 可持久化trie+trie
思路倒是不难,但是这题卡常啊 ~ code: #include <bits/stdc++.h> #define N 2000004 #define M 1000005 #define SI ...
- 【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成功培育出神牛细胞,可最终培育出的生物体却让他大失所望...... 后来,他从某同校女神 牛处知道,原来他培育的细胞发生了基因突变 ...
- [BZOJ4212]神牛的养成计划
[BZOJ4212]神牛的养成计划 试题描述 Hzwer 成功培育出神牛细胞,可最终培育出的生物体却让他大失所望...... 后来,他从某同校女神 牛处知道,原来他培育的细胞发生了基因突变,原先决定神 ...
- BZOJ.2741.[FOTILE模拟赛]L(分块 可持久化Trie)
题目链接 首先记\(sum\)为前缀异或和,那么区间\(s[l,r]=sum[l-1]^{\wedge}sum[r]\).即一个区间异或和可以转为求两个数的异或和. 那么对\([l,r]\)的询问即求 ...
- bzoj 3261: 最大异或和 (可持久化trie树)
3261: 最大异或和 Time Limit: 10 Sec Memory Limit: 512 MB Description 给定一个非负整数序列 {a},初始长度为 N. ...
- bzoj 3261 最大异或和【可持久化trie】
因为在后面加数字又求后缀和太麻烦,所以xor[p...n]=xor[1...n]^xor[p-1...n]. 首先处理出来区间异或前缀和,对前缀和建trie树(在最前面放一棵0表示最开始的前缀和 然后 ...
- Luogu5283 十二省联考2019异或粽子(trie/可持久化trie+堆)
做前缀异或和,用堆维护一个五元组(x,l,r,p,v),x为区间右端点的值,l~r为区间左端点的范围,p为x在l~r中最大异或和的位置,v为该最大异或和,每次从堆中取出v最大的元素,以p为界将其切成两 ...
随机推荐
- Python——将高德坐标(GCJ02)转换为GPS(WGS84)坐标
# 官方API: http://lbs.amap.com/api/webservice/guide/api/convert # 坐标体系说明:http://lbs.amap.com/faq/top/c ...
- macOS Mojave配置OpenGL开发环境
---恢复内容开始--- 前言: 本文写作目的: 是由于本人参考 csdn原文 的方法配置环境时踩了很多坑,所以在此写一篇文防止以后用到. 工具: Xcode CMake 步骤: 准备工作: Xcod ...
- addEventListener解决多个window.onscroll共存的2个方法
方法1.(注意第一个和第二个的先后次序) window.onscroll=function(){console.log('第一个');} var oldMethod = window.onscroll ...
- 电脑右键新建excel工作表,但是扩展名是.xls,而不是.xlsx
怀疑是因为之前安装了wps,然后又卸载了,导致的.上网查阅,如下: excel默认新建xls 不是我的问题 Excel 2010/2013/2016在鼠标右键新建xls或xlsx文件后,打开报错“无法 ...
- 提交变更(git commit)
当所有的变更都进入暂存区,就可以使用git commit进行提交了 $ git commit 执行这句话后,会弹出文本编辑区(自己配置的或默认的),文本编辑器可能会显示如下内容 # Please en ...
- 只要三步,使用html5+js实现像素风头像生成器
只要三步,使用html5+js实现像素风头像生成器 html5的画布给我们带来了很大的空间,其实像素风格头像生成器只是用到了画方块的方法.画一个像素头像,只要三步,1.解决像素点,2.解决像素点之间的 ...
- pmi-ACP考试知识点梳理(部分)
敏捷宣言 个体和互动 高于流程和工具 工作的软件 高于详尽的文档 客户合作 高于合同谈判 响应变化 高于遵循计划 十二条敏捷原则 1 我们最重要的目标,是通过持续不断地及早交付有价值的软件使客户满意. ...
- emos邮件系统的web密码修改方法
作者:邓聪聪 1.修改web管理界面的登陆密码,数据库修改管理员密码,有root用root,没root用系统用户.查看方法 进入数据库查看到管理表项中的root管理账户信息, mysql> u ...
- 简单易懂的解释c#的abstract和virtual的用法和区别
先来看abstract方法,顾名思义,abstract方法就是抽象方法. 1.抽象方法就是没有实现的,必须是形如: public abstract void Init(); 2.拥有抽象方法的类必须修 ...
- python正则表达式--match search方法
1.re.match函数 re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回None. (1)函数语法: re.match(pattern, st ...