Description

(我并不想告诉你题目名字是什么鬼)

有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n].

现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示),求这些后缀两两之间的LCP(LongestCommonPrefix)的长度之和.一对后缀之间的LCP长度仅统计一遍.

Input

第一行两个正整数n,m,分别表示S的长度以及询问的次数.

接下来一行有一个字符串S.

接下来有m组询问,对于每一组询问,均按照以下格式在一行内给出:

首先是一个整数t,表示共有多少个后缀.接下来t个整数分别表示t个后缀在字符串S中的出现位置.

Output

对于每一组询问,输出一行一个整数,表示该组询问的答案.由于答案可能很大,仅需要输出这个答案对于23333333333333333(一个巨大的质数)取模的余数.
建出后缀树,询问相当于后缀树上一些点间两两的lca的深度之和,建出虚树然后树形dp求解
  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. typedef long long i64;
  5. const int N=1e6+;
  6. char s[N];
  7. int nx[N][],l[N],fa[N],pp=,pv=;
  8. int n,m,pos[N];
  9. int e0[N],es[N],enx[N],ep=,sz[N],son[N],dep[N],top[N],id[N][],idp=,ss[N],sp=;
  10. int ed[N],tk=;
  11. char buf[],*ptr=buf-;
  12. int _(){
  13. int x=;
  14. while(*ptr<)++ptr;
  15. while(*ptr>)x=x*+*ptr++-;
  16. return x;
  17. }
  18. void _(char*s){
  19. while(*ptr<)++ptr;
  20. while(*ptr>)*s++=*ptr++;
  21. *ptr=;
  22. }
  23. int ins(int x){
  24. int p=pv,np=++pp;
  25. l[np]=l[p]+;
  26. while(p&&!nx[p][x])nx[p][x]=np,p=fa[p];
  27. if(!p)fa[np]=;
  28. else{
  29. int q=nx[p][x];
  30. if(l[q]==l[p]+)fa[np]=q;
  31. else{
  32. int nq=++pp;
  33. l[nq]=l[p]+;
  34. memcpy(nx[nq],nx[q],sizeof(nx[]));
  35. fa[nq]=fa[q];
  36. fa[q]=fa[np]=nq;
  37. while(p&&nx[p][x]==q)nx[p][x]=nq,p=fa[p];
  38. }
  39. }
  40. return pv=np;
  41. }
  42. void push(int w){
  43. ss[++sp]=w;
  44. id[w][]=++idp;
  45. dep[w]=dep[fa[w]]+;
  46. }
  47. void hld_pre(){
  48. for(int i=;i<=pp;++i){
  49. es[ep]=i;enx[ep]=e0[fa[i]];e0[fa[i]]=ep++;
  50. sz[i]=;
  51. }
  52. push();
  53. while(sp){
  54. int w=ss[sp],&e=e0[w];
  55. if(!e){
  56. int f=fa[w];
  57. sz[f]+=sz[w];
  58. if(w[sz]>f[son][sz])f[son]=w;
  59. id[w][]=idp;
  60. --sp;
  61. continue;
  62. }
  63. int u=es[e];
  64. e=enx[e];
  65. push(u);
  66. }
  67. for(int i=;i<=pp;++i)if(i[fa][son]!=i){
  68. for(int w=i;w;w=w[son])w[top]=i;
  69. }
  70. }
  71. int lca(int x,int y){
  72. int a=top[x],b=top[y];
  73. while(a!=b){
  74. if(dep[a]>dep[b])x=fa[a],a=top[x];
  75. else y=fa[b],b=top[y];
  76. }
  77. return dep[x]<dep[y]?x:y;
  78. }
  79. bool cmp(int a,int b){
  80. return id[a][]<id[b][];
  81. }
  82. int cs[N],cp,tp[N],_f[N];
  83. void cal(){
  84. i64 ans=;
  85. int p=;
  86. _f[ss[++sp]=cs[p++]]=;
  87. while(sp){
  88. int w=ss[sp];
  89. if(p<cp&&id[cs[p]][]<=id[w][])_f[ss[++sp]=cs[p++]]=w;
  90. else{
  91. --sp;
  92. int f=_f[w];
  93. if(f>){
  94. ans+=i64(l[f])*tp[f]*tp[w];
  95. tp[f]+=tp[w];
  96. }
  97. }
  98. }
  99. printf("%lld\n",ans);
  100. }
  101. int main(){
  102. fread(buf,,sizeof(buf),stdin)[buf]=;
  103. n=_();m=_();
  104. _(s+);
  105. for(int i=n;i;--i)pos[i]=ins(s[i]-'a');
  106. hld_pre();
  107. for(int c;m;--m){
  108. c=_();
  109. cp=;
  110. ++tk;
  111. for(int i=,x;i<c;++i){
  112. x=pos[_()];
  113. if(ed[x]!=tk)ed[cs[cp++]=x]=tk,tp[x]=;
  114. }
  115. std::sort(cs,cs+cp,cmp);
  116. c=cp;
  117. for(int i=,pv=;i<c;++i){
  118. int x=lca(cs[i],pv);
  119. pv=cs[i];
  120. if(ed[x]!=tk)ed[cs[cp++]=x]=tk,tp[x]=;
  121. }
  122. std::sort(cs,cs+cp,cmp);
  123. cal();
  124. }
  125. return ;
  126. }

bzoj 3879: SvT的更多相关文章

  1. ●BZOJ 3879 SvT

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3879 题解: 后缀数组,单调栈,RMQ 其实类似 BZOJ 3238 [Ahoi2013]差 ...

  2. BZOJ 3879: SvT [虚树 后缀树]

    传送门 题意: 多次询问,给出一些后缀,求两两之间$LCP$之和 哈哈哈哈哈哈哈竟然$1A$了,刚才还在想如果写不好这道题下节数学就不上了,看来是上天让我上数学课啊 $Suffix\ Virtual\ ...

  3. BZOJ 3879: SvT 虚树 + 后缀自动机

    Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始 ...

  4. 【BZOJ 3879】SvT

    http://www.lydsy.com/JudgeOnline/problem.php?id=3879 SvT的中文是后缀虚树? 反正本蒟蒻不懂,还是$O(nlogn)$的后缀数组和单调栈维护来做, ...

  5. bzoj 3879 虚树

    题目大意: 给一个字符串,多次询问k个后缀,求它们两两间LCP长度总和 分析: 转化为后缀树,用虚树求 注意: 后缀树中代表后缀的点都是叶子节点 题目中取模并没有卵用 #include <cst ...

  6. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  7. Week Four

    2018.12.18 1.[USACO Platinum C] 2.[Gym 102028H] 3.[BZOJ 2750] 4.[BZOJ 3238] 5.[BZOJ 4310] 6.[BZOJ 38 ...

  8. Week Five

    2018.12.25 1.[BZOJ 4310] 2.[BZOJ 3879] 3.[BZOJ 2754] 4.[BZOJ 4698] 5.[Codeforces 914E] 6.[Codeforces ...

  9. HDU 3879 && BZOJ 1497:Base Station && 最大获利 (最大权闭合图)

    http://acm.hdu.edu.cn/showproblem.php?pid=3879 http://www.lydsy.com/JudgeOnline/problem.php?id=1497 ...

随机推荐

  1. TC 配置插件

    转载:http://hi.baidu.com/accplaystation/item/07534686f39dc329100ef310 1.插件下载地址:http://www.topcoder.com ...

  2. redis高可用 - redis集群

    redis-sentinel方案提供了单点的高可用解决方案,但是当数据量和业务量极速增长时,单点的reids不可能无限的纵向扩容(增大内存),这个时候就需要redis有集群的能力来扛. redis集群 ...

  3. mysql之innodb的锁分类介绍

    一.innodb行锁分类 record lock:记录锁,也就是仅仅锁着单独的一行 gap lock:区间锁,仅仅锁住一个区间(注意这里的区间都是开区间,也就是不包括边界值. next-key loc ...

  4. MVP框架模式

    一.基本概念 MVP是Model-View-Presenter的简称,即模型-视图-表现层的缩写.MVP是由MVC模式进化而来的,MVP改进了MVC中的控制器过于臃肿的问题.与MVC一样,MVP将应用 ...

  5. Android------视频播放器(包含全屏播放,快退,快进,腾讯新闻的列表播放等)

    前段时间做了一个新闻APP,涉及到了列表视频播放,和腾讯新闻APP差不多,总结了一下代码,写了一个Demo来分享给大家. 用了  TabLayout+RecylerView+自定义视频控件  完成的 ...

  6. 流量监控iftop安装-CentOS7

    继之前撘的服务器后路由器一直崩溃,今天找到了原因.之前被下的木马并没有被删掉,而是一直在传输数据.占用了所有宽带. 官网(http://www.ex-parrot.com/pdw/iftop/down ...

  7. Java实现ping功能的三种方法及Linux的区分

    前大半部份转自:https://blog.csdn.net/futudeniaodan/article/details/52317650 检测设备的运行状态,有的是使用ping的方式来检测的.所以需要 ...

  8. CF86D

    题解: 莫队分块 分块大小为sqrt(n) 代码: #include<bits/stdc++.h> using namespace std; ; typedef long long ll; ...

  9. java基础11天

    冒泡排序 相邻元素两两比较,大的往后放,第一次完毕,最大值出现在了最大索引处,第二次比较厚,最大值放在了倒数第二的位置,一直到第二个元素确定了,整个数组的顺序也就确定了 public class Ar ...

  10. JSP Unable to compile class for JSP

    今天刚弄好MyEclipse环境,试了一下jsp的创建,然后就出现了一个很令人纠结的问题. 文档目录如下: Jsp代码如下: <%@page import="com.pd.Person ...