这题解法很多,简单说几个:

1. 线段树合并,时间复杂度是 $O(nlog^2n)$ 的.

2. 暴力跳 $fail,$ 时间复杂度 $O(n\sqrt n),$ 比较暴力.

3. 建立后缀树后在 $dfs$ 序上数点,时间复杂度为 $O(nlogn),$ 十分优秀.

Code:

#include <bits/stdc++.h>
#define N 200007
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)
using namespace std;
struct ques
{
int l,r,id;
ques(int l=0,int r=0,int id=0):l(l),r(r),id(id){}
}q[N];
struct P
{
int len,f,ch[27];
vector<int>v;
}t[N<<1];
char S[N];
vector<int>G[N];
int tot,last,edges,tim,cnt;
int hd[N],to[N],nex[N],st[N],ed[N],size[N],dfn[N],lst[N],C[N],answer[N];
int lowbit(int t)
{
return t&(-t);
}
void update(int x,int delta)
{
for(;x<N;x+=lowbit(x)) C[x]+=delta;
}
int query(int x)
{
int tmp=0;
for(;x>0;x-=lowbit(x)) tmp+=C[x];
return tmp;
}
bool cmp(ques a,ques b)
{
return a.r<b.r;
}
void addedge(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void extend(int c,int id)
{
if(t[last].ch[c])
{
int p=last;
int q=t[p].ch[c];
if(t[q].len==t[p].len+1) last=q;
else
{
int nq=++tot;
t[nq].len=t[p].len+1;
t[nq].f=t[q].f,t[q].f=nq;
memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch));
for(;p&&t[p].ch[c]==q;p=t[p].f) t[p].ch[c]=nq;
last=nq;
}
}
else
{
int np=++tot,p=last;
t[np].len=t[p].len+1,last=np;
for(;p&&!t[p].ch[c];p=t[p].f) t[p].ch[c]=np;
if(!p) t[np].f=1;
else
{
int q=t[p].ch[c];
if(t[q].len==t[p].len+1) t[np].f=q;
else
{
int nq=++tot;
t[nq].len=t[p].len+1;
t[nq].f=t[q].f,t[q].f=t[np].f=nq;
memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch));
for(;p&&t[p].ch[c]==q;p=t[p].f) t[p].ch[c]=nq;
}
}
}
t[last].v.push_back(id);
}
void dfs(int u)
{
dfn[u]=st[u]=++tim;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
dfs(v);
}
for(int k=0;k<t[u].v.size();++k)
G[dfn[u]].push_back(t[u].v[k]);
ed[u]=tim;
}
int main()
{
last=tot=1;
int i,j,n,m,k;
// setIO("input");
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i)
{
last=1;
scanf("%s",S+1);
int len=strlen(S+1);
for(j=1;j<=len;++j) extend(S[j]-'a',i);
}
for(i=2;i<=tot;++i)
addedge(t[i].f,i);
dfs(1);
for(i=1;i<=m;++i)
{
scanf("%s",S+1);
int len=strlen(S+1),p=1;
for(j=1;j<=len;++j)
{
int c=S[j]-'a';
if(!t[p].ch[c])
{
p=-1;
break;
}
else p=t[p].ch[c];
}
if(p!=-1) q[++cnt]=ques(st[p],ed[p],i);
}
sort(q+1,q+1+cnt,cmp);
for(j=i=1;i<=cnt;++i)
{
for(;j<=q[i].r;++j)
{
for(k=0;k<G[j].size();++k)
{
int tt=G[j][k];
if(lst[tt]) update(lst[tt],-1);
lst[tt]=j;
update(j,1);
}
}
answer[q[i].id]=query(q[i].r)-query(q[i].l-1);
}
for(i=1;i<=m;++i) printf("%d\n",answer[i]);
return 0;
}

  

luogu SP8093 后缀自动机+树状数组+dfs序的更多相关文章

  1. BZOJ 2780 Sevenk Love Oimaster (后缀自动机+树状数组+dfs序+离线)

    题目大意: 给你$n$个大串和$m$个询问,每次给出一个字符串$s$询问在多少个大串中出现过 好神的一道题 对$n$个大串建出广义$SAM$,建出$parent$树 把字符串$s$放到$SAM$里跑, ...

  2. 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

    [题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...

  3. BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)

    题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...

  4. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  5. 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序

    3881: [Coci2015]Divljak Time Limit: 20 Sec  Memory Limit: 768 MBSubmit: 508  Solved: 158[Submit][Sta ...

  6. [luogu P3787][新创无际夏日公开赛] 冰精冻西瓜 [树状数组][dfs序]

    题目背景 盛夏,冰之妖精琪露诺发现了一大片西瓜地,终于可以吃到美味的冻西瓜啦. 题目描述 琪露诺是拥有操纵冷气程度的能力的妖精,一天她发现了一片西瓜地.这里有n个西瓜,由n-1条西瓜蔓连接,形成一个有 ...

  7. 【BZOJ-1103】大都市meg 树状数组 + DFS序

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2009  Solved: 1056[Submit][Sta ...

  8. POJ 3321 Apple Tree (树状数组+dfs序)

    题目链接:http://poj.org/problem?id=3321 给你n个点,n-1条边,1为根节点.给你m条操作,C操作是将x点变反(1变0,0变1),Q操作是询问x节点以及它子树的值之和.初 ...

  9. BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1103 [题目大意] 给出一棵树,每条边的经过代价为1,现在告诉你有些路不需要代价了, ...

随机推荐

  1. Numpy学习之——数组创建

    Numpy学习之--数组创建 过程展示 import numpy as np a = np.array([2,3,9]) a array([2, 3, 9]) a.dtype dtype('int32 ...

  2. unittest参数化(paramunittest)

    前言 paramunittest是unittest实现参数化的一个专门的模块,可以传入多组参数,自动生成多个用例前面讲数据驱动的时候,用ddt可以解决多组数据传入,自动生成多个测试用例.本篇继续介绍另 ...

  3. Oracle 表分区介绍与使用

    什么是表分区 分区表是将大表的数据分成称为分区的许多小的子集,类型有FAT32,NTFST32,NTFS.另外,分区表的种类划分主要有:range,list,和hash分区.划分依据主要是根据其表内部 ...

  4. hdu 3500 还是搜索

    这道题目由于每走一步的时候毛毛球是可以变换的 换言之 主体不唯一 所以这里搜索的设计有变化 再就是几个回溯的过程要注意.,.  小心使得万年船 #include <iostream> #i ...

  5. Java lesson08 Homework

    1:1. 写一个类Param,声明四个成员变量a.b.c.d,分别赋予四种访问权限. (1)试验在同一个包中的另一个类里能访问哪几个变量? (2)试验在不同包中的另一个类里能访问哪几个变量? (3)试 ...

  6. layer,备受青睐的web弹层组件

    //http://layer.layui.com/ 特别说明:事件需自己绑定,以下只展现调用代码. //初体验 layer.alert('内容') //第三方扩展皮肤 layer.alert('内容' ...

  7. STM32 USB Virtual COM

    STM32 USB Virtual COM USB转串口的功能实现   这次讲的是如何实现USB转串口功能的实现.首先看看工程的布局吧: 我们主要要介绍的文件的在USB_User这个组文件.从上面的截 ...

  8. kubernetes 集群内部访问外部的数据库endpoint

    k8s访问集群外独立的服务最好的方式是采用Endpoint方式,以mysql服务为例: 创建mysql-service.yaml apiVersion: v1 kind: Service metada ...

  9. CNN 笔记

    1. 卷积后的图像的大小为    (w+2p-f)*3 / s    W为图像的宽,p为padding的大小, f为卷积核大小, 3 为图像的通道数, s为步长 2. 卷积层和池化层的区别? 卷积层是 ...

  10. 升级openssh到高版本

    linux升级openssh到高版本 可以解决OpenSSH 安全漏洞(CVE-2018-15919)和SSH服务器类型和版本 如果是新服务器,需要安装对应命令vim 上传下载等命令 安装上传或者下载 ...