bzoj 3879: SvT
Description
(我并不想告诉你题目名字是什么鬼)
有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n].
现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示),求这些后缀两两之间的LCP(LongestCommonPrefix)的长度之和.一对后缀之间的LCP长度仅统计一遍.
Input
第一行两个正整数n,m,分别表示S的长度以及询问的次数.
接下来一行有一个字符串S.
接下来有m组询问,对于每一组询问,均按照以下格式在一行内给出:
首先是一个整数t,表示共有多少个后缀.接下来t个整数分别表示t个后缀在字符串S中的出现位置.
Output
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long i64;
const int N=1e6+;
char s[N];
int nx[N][],l[N],fa[N],pp=,pv=;
int n,m,pos[N];
int e0[N],es[N],enx[N],ep=,sz[N],son[N],dep[N],top[N],id[N][],idp=,ss[N],sp=;
int ed[N],tk=;
char buf[],*ptr=buf-;
int _(){
int x=;
while(*ptr<)++ptr;
while(*ptr>)x=x*+*ptr++-;
return x;
}
void _(char*s){
while(*ptr<)++ptr;
while(*ptr>)*s++=*ptr++;
*ptr=;
}
int ins(int x){
int p=pv,np=++pp;
l[np]=l[p]+;
while(p&&!nx[p][x])nx[p][x]=np,p=fa[p];
if(!p)fa[np]=;
else{
int q=nx[p][x];
if(l[q]==l[p]+)fa[np]=q;
else{
int nq=++pp;
l[nq]=l[p]+;
memcpy(nx[nq],nx[q],sizeof(nx[]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while(p&&nx[p][x]==q)nx[p][x]=nq,p=fa[p];
}
}
return pv=np;
}
void push(int w){
ss[++sp]=w;
id[w][]=++idp;
dep[w]=dep[fa[w]]+;
}
void hld_pre(){
for(int i=;i<=pp;++i){
es[ep]=i;enx[ep]=e0[fa[i]];e0[fa[i]]=ep++;
sz[i]=;
}
push();
while(sp){
int w=ss[sp],&e=e0[w];
if(!e){
int f=fa[w];
sz[f]+=sz[w];
if(w[sz]>f[son][sz])f[son]=w;
id[w][]=idp;
--sp;
continue;
}
int u=es[e];
e=enx[e];
push(u);
}
for(int i=;i<=pp;++i)if(i[fa][son]!=i){
for(int w=i;w;w=w[son])w[top]=i;
}
}
int lca(int x,int y){
int a=top[x],b=top[y];
while(a!=b){
if(dep[a]>dep[b])x=fa[a],a=top[x];
else y=fa[b],b=top[y];
}
return dep[x]<dep[y]?x:y;
}
bool cmp(int a,int b){
return id[a][]<id[b][];
}
int cs[N],cp,tp[N],_f[N];
void cal(){
i64 ans=;
int p=;
_f[ss[++sp]=cs[p++]]=;
while(sp){
int w=ss[sp];
if(p<cp&&id[cs[p]][]<=id[w][])_f[ss[++sp]=cs[p++]]=w;
else{
--sp;
int f=_f[w];
if(f>){
ans+=i64(l[f])*tp[f]*tp[w];
tp[f]+=tp[w];
}
}
}
printf("%lld\n",ans);
}
int main(){
fread(buf,,sizeof(buf),stdin)[buf]=;
n=_();m=_();
_(s+);
for(int i=n;i;--i)pos[i]=ins(s[i]-'a');
hld_pre();
for(int c;m;--m){
c=_();
cp=;
++tk;
for(int i=,x;i<c;++i){
x=pos[_()];
if(ed[x]!=tk)ed[cs[cp++]=x]=tk,tp[x]=;
}
std::sort(cs,cs+cp,cmp);
c=cp;
for(int i=,pv=;i<c;++i){
int x=lca(cs[i],pv);
pv=cs[i];
if(ed[x]!=tk)ed[cs[cp++]=x]=tk,tp[x]=;
}
std::sort(cs,cs+cp,cmp);
cal();
}
return ;
}
bzoj 3879: SvT的更多相关文章
- ●BZOJ 3879 SvT
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3879 题解: 后缀数组,单调栈,RMQ 其实类似 BZOJ 3238 [Ahoi2013]差 ...
- BZOJ 3879: SvT [虚树 后缀树]
传送门 题意: 多次询问,给出一些后缀,求两两之间$LCP$之和 哈哈哈哈哈哈哈竟然$1A$了,刚才还在想如果写不好这道题下节数学就不上了,看来是上天让我上数学课啊 $Suffix\ Virtual\ ...
- BZOJ 3879: SvT 虚树 + 后缀自动机
Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始 ...
- 【BZOJ 3879】SvT
http://www.lydsy.com/JudgeOnline/problem.php?id=3879 SvT的中文是后缀虚树? 反正本蒟蒻不懂,还是$O(nlogn)$的后缀数组和单调栈维护来做, ...
- bzoj 3879 虚树
题目大意: 给一个字符串,多次询问k个后缀,求它们两两间LCP长度总和 分析: 转化为后缀树,用虚树求 注意: 后缀树中代表后缀的点都是叶子节点 题目中取模并没有卵用 #include <cst ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- Week Four
2018.12.18 1.[USACO Platinum C] 2.[Gym 102028H] 3.[BZOJ 2750] 4.[BZOJ 3238] 5.[BZOJ 4310] 6.[BZOJ 38 ...
- Week Five
2018.12.25 1.[BZOJ 4310] 2.[BZOJ 3879] 3.[BZOJ 2754] 4.[BZOJ 4698] 5.[Codeforces 914E] 6.[Codeforces ...
- HDU 3879 && BZOJ 1497:Base Station && 最大获利 (最大权闭合图)
http://acm.hdu.edu.cn/showproblem.php?pid=3879 http://www.lydsy.com/JudgeOnline/problem.php?id=1497 ...
随机推荐
- Redis之Sorted Set 有序集合
Redis Sorted Set 有序集合 Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过分 ...
- Flask 5 模板1
NOTE 1.VF的作用:生成请求的响应.一般来说请求会改变程序的状态,这种变化会在视图函数中产生. eg.用户在网站中注册了一个新账户,用户在表单中输入电子邮件地址和密码,然后提交到服务器,服务器接 ...
- install ros-indigo-tf2
sudo apt-get install ros-indigo-tf2
- 解决Error: ENOENT: no such file or directory, scandir 安装node-sass报错
新项目开发需要安装依赖,但是安装完之后通过gulp运行项目,产生了一下的报错: 解决方案是执行一些方法: npm rebuild node-sass 可是有时就是网络问题导致上面命令安装失败,查下失败 ...
- Linux命令详解-printf
printf命令格式化并输出结果到标准输出. 1.命令格式: printf (选项) (参数) 2.命令功能: echo会将输入的字符串送往标准输出.输出的字符串间以空白字符隔开,并在最后加上换行号. ...
- 1003: [ZJOI2006]物流运输 最短路+dp
https://www.lydsy.com/JudgeOnline/problem.php?id=1003 数据范围很小,怎么瞎搞都行,n方dp,然后跑出最短路暴力转移,需要注意的是不能使用的可能有多 ...
- Java线程状态分析
Java线程的生命周期中,存在几种状态.在Thread类里有一个枚举类型State,定义了线程的几种状态,分别有: NEW: 线程创建之后,但是还没有启动(not yet started).这时候它的 ...
- C#属性升级版--自动属性-chapter 3 P34-36
使用C#属性,能够通过将数据与它的设置和检索方法分离的方式公开类中的一段数据. 例如: namespace LanguageFeatures { public class Product { ...
- 在EORow或者VORow中对数据进行重复性校验
需求:在设置付款条件时不允许账期+付款方式重复. 由于本次需求仅需要对VO缓存中的数据进行重复性校验,所以仅需进行缓存遍历即可,不需要校验数据库. 方式1,在EORow的进行数据校验. public ...
- Swagger使用总结(十九)
1. Swagger是什么? Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件. 官方说法:Swagger是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTfu ...