原问题可以转化为:给定第k个字符串,求它在L-R的字符串里作为子串出现了多少次

定义子串为字符串的某个前缀的某个后缀(废话)

等价于我们把一个字符串插入到trie里,其过程中每个经过的节点和其向上的fail链上的点都是该字符串的子串

又因为对于一条fail链,u向上能访问到v当前仅当u在v的子树内

那么原问题又变成了:

将L-R个字符串按照上述方法插入到trie中并将经过的节点的val值增加

求第k个字符串对应的单词节点在fail树上的子树的权值和

又因为查询的信息满足区间可减性,所以我们可以建出fail树

对fail树用可持久化线段树维护DFS序 完成单点修改和子树查询

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<iostream>
  5. #include<algorithm>
  6. #include<queue>
  7. using namespace std;
  8.  
  9. const int maxn=500010;
  10. int n,m,sum=0;
  11. int L,R,k;
  12. int pos[maxn];
  13. int rt[maxn];
  14. char s[maxn];
  15. queue<int>Q;
  16.  
  17. int h[maxn],cnt=0;
  18. int A[maxn],B[maxn],tot=0;
  19. struct edge{
  20. int to,next;
  21. }G[maxn<<1];
  22.  
  23. void add(int x,int y){++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;}
  24. void Get_DFS(int u){
  25. A[u]=++tot;
  26. for(int i=h[u];i;i=G[i].next)Get_DFS(G[i].to);
  27. B[u]=tot;
  28. }
  29.  
  30. struct Seg_Tree{
  31. int L,R,v;
  32. }t[11000010];
  33.  
  34. void build(int &o,int L,int R){
  35. o=++sum;
  36. if(L==R)return;
  37. int mid=(L+R)>>1;
  38. build(t[o].L,L,mid);
  39. build(t[o].R,mid+1,R);
  40. }
  41. void modify(int &o,int L,int R,int p){
  42. t[++sum]=t[o];o=sum;
  43. if(L==R){t[o].v++;return;}
  44. int mid=(L+R)>>1;
  45. if(p<=mid)modify(t[o].L,L,mid,p);
  46. else modify(t[o].R,mid+1,R,p);
  47. t[o].v=t[t[o].L].v+t[t[o].R].v;
  48. }
  49. int ask(int o,int L,int R,int x,int y){
  50. if(L>=x&&R<=y)return t[o].v;
  51. int mid=(L+R)>>1;
  52. if(y<=mid)return ask(t[o].L,L,mid,x,y);
  53. else if(x>mid)return ask(t[o].R,mid+1,R,x,y);
  54. else return ask(t[o].L,L,mid,x,y)+ask(t[o].R,mid+1,R,x,y);
  55. }
  56.  
  57. struct Trie{
  58. int cnt;
  59. int t[maxn][26];
  60. int fail[maxn],fa[maxn];
  61. void init(){
  62. cnt=1;fail[0]=1;
  63. for(int i=0;i<26;++i)t[0][i]=1;
  64. }
  65. int insert(){
  66. int len=strlen(s+1);
  67. int now=1;
  68. for(int i=1;i<=len;++i){
  69. int id=s[i]-'a';
  70. if(!t[now][id])t[now][id]=++cnt,fa[t[now][id]]=now;
  71. now=t[now][id];
  72. }return now;
  73. }
  74. void build_fail(){
  75. Q.push(1);fail[1]=0;
  76. while(!Q.empty()){
  77. int u=Q.front();Q.pop();
  78. for(int i=0;i<26;++i){
  79. if(t[u][i]){
  80. int k=fail[u];
  81. while(!t[k][i])k=fail[k];
  82. fail[t[u][i]]=t[k][i];
  83. add(t[k][i],t[u][i]);
  84. Q.push(t[u][i]);
  85. }
  86. }
  87. }return;
  88. }
  89. void UPD(){
  90. build(rt[0],1,cnt);
  91. for(int i=1;i<=n;++i){
  92. rt[i]=rt[i-1];
  93. for(int j=pos[i];j!=1;j=fa[j]){
  94. modify(rt[i],1,cnt,A[j]);
  95. }
  96. }return;
  97. }
  98. }AC;
  99.  
  100. int main(){
  101. scanf("%d%d",&n,&m);
  102. AC.init();
  103. for(int i=1;i<=n;++i){
  104. scanf("%s",s+1);
  105. pos[i]=AC.insert();
  106. }AC.build_fail();Get_DFS(1);AC.UPD();
  107. for(int i=1;i<=m;++i){
  108. scanf("%d%d%d",&L,&R,&k);
  109. printf("%d\n",ask(rt[R],1,AC.cnt,A[pos[k]],B[pos[k]])-ask(rt[L-1],1,AC.cnt,A[pos[k]],B[pos[k]]));
  110. }return 0;
  111. }

  

即可

codeforces #305 E Mike and friends的更多相关文章

  1. codeforces #305 A Mike and Frog

    挺简单的题目,但是有一堆恶心的边界 在刨去恶心的边界之后: 假定我们知道两边的循环节为b1,b2 其中h第一次到达目标的时间为a1,a2 又知道对于答案t t=a1+b1*t1=a2+b2*t2 不妨 ...

  2. codeforces #305 B Mike and Feet

    跟之前做过的51Nod的移数博弈是一样的QAQ 我们考虑每个数的贡献 定义其左边第一个比他小的数的位置为L 定义其右边第一个比他小的数的位置为R 这个可以用排序+链表 或者 单调队列 搞定 那么对于区 ...

  3. codeforces #305 D Mike and Fish

    正解貌似是大暴搜? 首先我们考虑这是一个二分图,建立网络流模型后很容易得出一个算法 S->行 容量为Num[X]/2; 行->列 容量为1 且要求(x,y)这个点存在 列->T 容量 ...

  4. codeforces #305 C Mike and Foam

    首先我们注意到ai<=50w 因为2*3*5*7*11*13*17=510510 所以其最多含有6个质因子 我们将每个数的贡献分离, 添加就等于加上了跟这个数相关的互素对 删除就等于减去了跟这个 ...

  5. Codeforces 547C/548E - Mike and Foam 题解

    目录 Codeforces 547C/548E - Mike and Foam 题解 前置芝士 - 容斥原理 题意 想法(口胡) 做法 程序 感谢 Codeforces 547C/548E - Mik ...

  6. (CodeForces 548B 暴力) Mike and Fun

    http://codeforces.com/problemset/problem/548/B Mike and some bears are playing a game just for fun. ...

  7. codeforces 361 E - Mike and Geometry Problem

    原题: Description Mike wants to prepare for IMO but he doesn't know geometry, so his teacher gave him ...

  8. codeforces 361 A - Mike and Cellphone

    原题: Description While swimming at the beach, Mike has accidentally dropped his cellphone into the wa ...

  9. codeforces 361 B - Mike and Shortcuts

    原题: Description Recently, Mike was very busy with studying for exams and contests. Now he is going t ...

随机推荐

  1. unity 5.3 以后加载场景

    记录下官方建议的加载场景的方法: StartCoroutine(LoadYourAsyncScene()); IEnumerator LoadYourAsyncScene() { // The App ...

  2. linux signal

    1) SIGHUP 本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联. 登录Linux时,系统会分配给 ...

  3. redis出现错误:NOAUTH Authentication required.

    出现认证问题,应该是设置了认证密码,输入密码既可以啦 注意密码是字符串形式! 127.0.0.1:6379> auth "yourpassword" 127.0.0.1:63 ...

  4. PHP利用get_headers()函数判断远程的url地址是否有效

    问题: 利用url访问远程的文件.图片.视频时有时需要请求前判断url地址是否有效. 解决办法: (PHP 5, PHP 7) get_headers — 取得服务器响应一个 HTTP 请求所发送的所 ...

  5. Maven setting.xml 文件配置

    全局配置: ${M2_HOME}/conf/settings.xml (配置环境变量  新建 M2_HOME    安装目录到版本名那里(D:\apache-maven-3.0.2) 编辑path 环 ...

  6. git最佳实践之feature和hotfix分支

    先来复习一波,git的最佳分支管理流程: 再简单复习各个分支: master: 主分支,主要用来版本发布. develop:日常开发分支,该分支正常保存了开发的最新代码. feature:具体的功能开 ...

  7. eclipse安装反编译decompiler方式一

    (转发位置:https://www.cnblogs.com/zs-notes/p/8991503.html) eclipse安装JD-eclipse反编译插件 1.在eclipse的help中选择In ...

  8. ajax获取后台数据渲染(整片文章不分段落)解决方案,要使用htmL方式输出

    方案一:使用 HTML pre tag<div class="content"><pre> {{ text_data }}</pre></ ...

  9. 在IOS应用中打开另外一个应用的解决方案

    最近要在IOS中实现一个应用启动另外一个应用的功能,搜了一些资料,使用UIApplication的openURL:的方法就能实现,现在整理和大家分享一下! 注册自定义URL协议 首先被启动的应用需要向 ...

  10. 倒计时48小时|2018GIAC上海站参会攻略来了!

    再过一天,令大家期待已久的GIAC全球互联网架构大会将登陆魔都与众位架构师.技术负责人及高端技术从业人员见面! 这场策划许久的技术盛宴,我们邀请到了腾讯.阿里.京东.美团.keep.UC.360.网商 ...