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

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

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

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

那么原问题又变成了:

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

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

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

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

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std; const int maxn=500010;
int n,m,sum=0;
int L,R,k;
int pos[maxn];
int rt[maxn];
char s[maxn];
queue<int>Q; int h[maxn],cnt=0;
int A[maxn],B[maxn],tot=0;
struct edge{
int to,next;
}G[maxn<<1]; void add(int x,int y){++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;}
void Get_DFS(int u){
A[u]=++tot;
for(int i=h[u];i;i=G[i].next)Get_DFS(G[i].to);
B[u]=tot;
} struct Seg_Tree{
int L,R,v;
}t[11000010]; void build(int &o,int L,int R){
o=++sum;
if(L==R)return;
int mid=(L+R)>>1;
build(t[o].L,L,mid);
build(t[o].R,mid+1,R);
}
void modify(int &o,int L,int R,int p){
t[++sum]=t[o];o=sum;
if(L==R){t[o].v++;return;}
int mid=(L+R)>>1;
if(p<=mid)modify(t[o].L,L,mid,p);
else modify(t[o].R,mid+1,R,p);
t[o].v=t[t[o].L].v+t[t[o].R].v;
}
int ask(int o,int L,int R,int x,int y){
if(L>=x&&R<=y)return t[o].v;
int mid=(L+R)>>1;
if(y<=mid)return ask(t[o].L,L,mid,x,y);
else if(x>mid)return ask(t[o].R,mid+1,R,x,y);
else return ask(t[o].L,L,mid,x,y)+ask(t[o].R,mid+1,R,x,y);
} struct Trie{
int cnt;
int t[maxn][26];
int fail[maxn],fa[maxn];
void init(){
cnt=1;fail[0]=1;
for(int i=0;i<26;++i)t[0][i]=1;
}
int insert(){
int len=strlen(s+1);
int now=1;
for(int i=1;i<=len;++i){
int id=s[i]-'a';
if(!t[now][id])t[now][id]=++cnt,fa[t[now][id]]=now;
now=t[now][id];
}return now;
}
void build_fail(){
Q.push(1);fail[1]=0;
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int i=0;i<26;++i){
if(t[u][i]){
int k=fail[u];
while(!t[k][i])k=fail[k];
fail[t[u][i]]=t[k][i];
add(t[k][i],t[u][i]);
Q.push(t[u][i]);
}
}
}return;
}
void UPD(){
build(rt[0],1,cnt);
for(int i=1;i<=n;++i){
rt[i]=rt[i-1];
for(int j=pos[i];j!=1;j=fa[j]){
modify(rt[i],1,cnt,A[j]);
}
}return;
}
}AC; int main(){
scanf("%d%d",&n,&m);
AC.init();
for(int i=1;i<=n;++i){
scanf("%s",s+1);
pos[i]=AC.insert();
}AC.build_fail();Get_DFS(1);AC.UPD();
for(int i=1;i<=m;++i){
scanf("%d%d%d",&L,&R,&k);
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]]));
}return 0;
}

  

即可

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. JavaScript 运行机制详解:Event Loop

    参考地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是 ...

  2. window alias给cmd命令起别名

    场景: Linux的alias命令是个非常实用的工具,任何命令通过alias可以精简到很短,比如:alias l='ls -l' Windows也有alias类似的命令,就是:doskey,开启方法也 ...

  3. Oracle同义词(synonym)

    oracle的同义词总结   从字面上理解就是别名的意思,和视图的功能类似.就是一种映射关系.   同义词拥有如下好处:   节省大量的数据库空间,对不同用户的操作同一张表没有多少差别;   扩展的数 ...

  4. Gym 100712

    我的作用:增加罚时. noip380分大佬全程带飞出了10T,可惜被我搞的罚时太高了... 那啥,你会发现java代码有两种风格,嗯两个人,c++自然就是自招大佬了... A:大水题略 B:(不是我写 ...

  5. java学习之路--集合基础之List和Set部分

    List 一个接口,它继承于Collection的接口.它代表着有序的队列.里面的元素是有序的,可以重复,因为该集合的体系有索引. List的实现类 ArrayList:底层数据结构为数组数据结构,特 ...

  6. juqery 给本身的class加上一个class 或也可以实现关注商品,取消关注商品

    $("#goods1").on("click",".ICON-fen-LOVE",function(){ var $this = $(thi ...

  7. 2018-2019-2 20165330《网络对抗技术》Exp5 MSF基础应用

    目录 基础问题 相关知识 实验目的 实验内容 实验步骤 离实战还缺些什么技术或步骤? 实验总结与体会 实验目的 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路 返回目 ...

  8. Linux下/usr/bin与/usr/local/bin/区别总结

    Linux下/usr/bin与/usr/local/bin/区别总结 2017年10月13日 12:30:17 2puT 阅读数:15930    版权声明:本文为博主原创文章! github地址:h ...

  9. 洛谷P4324 扭动的回文串 [JSOI2016] manacher+哈希

    正解:manacher+哈希 解题报告: 传送门 要不要先解释下题意,,,我开始看了半天来着QAQ 大概就,要求一个最长的回文串 这个回文串有两种构成可能 一种是单从一个串中拿出来的连续一段 另一种是 ...

  10. h5新增标签及css3新增属性

    - h5新增的标签 新增元素 说明 video 表示一段视频并提供播放的用户界面 audio 表示音频 canvas 表示位图区域 source 为video和audio提供数据源 track 为vi ...