ac自动机fail树上按询问建立上跳指针——cf963D
解法看着吓人,其实就是为了优化ac自动机上暴力跳fail指针。。
另外这题对于复杂度的分析很有学习价值
/*
给定一个母串s,再给定n个询问(k,m)
对于每个询问,求出长度最小的t,使t是s的子串,且m作为子串在t中出现了m次 对多串建立ac自动机,然后用s去匹配,把所有询问的出现位置都用vector保存下来
然后对应每个询问的k进行更新答案 为了保证复杂度:在跳fail不能暴力向上跳,应该直接用一个指针pre跳到上一个带有询问的点
这样每次向上跳都让某个询问的vector更新进一个新的值
由于最多有sqrt(n)个不同的询问串长度,所以以每个s[i]为结尾的可匹配串也只有sqrt(n)个,
即最多在fail树上跳nsqrt(n)次
*/
#include<bits/stdc++.h>
using namespace std;
#define N 200005 struct Query{
vector<int>pos;
int k,len;
}q[N];
char s[N],buf[N];
int n; struct Trie{
int nxt[N][],fail[N],id[N],pre[N];
int root,L;
int newnode(){
memset(nxt[L],-,sizeof nxt[L]);
id[L]=;
return L++;
}
void init(){L=;root=newnode();}
void insert(char buf[],int ID){
int len=strlen(buf);
int now=root;
for(int i=;i<len;i++){
if(nxt[now][buf[i]-'a']==-)
nxt[now][buf[i]-'a']=newnode();
now=nxt[now][buf[i]-'a'];
}
id[now]=ID;
}
void build(){
queue<int>q;
fail[root]=root;
for(int i=;i<;i++)
if(nxt[root][i]==-)
nxt[root][i]=root;
else {
fail[nxt[root][i]]=root;
q.push(nxt[root][i]);
}
pre[root]=; while(q.size()){
int now=q.front();q.pop();//此时now的fail已经建立好
if(id[fail[now]]!=)//找上一个询问的位置
pre[now]=fail[now];
else
pre[now]=pre[fail[now]]; for(int i=;i<;i++)
if(nxt[now][i]==-)
nxt[now][i]=nxt[fail[now]][i];
else {
fail[nxt[now][i]]=nxt[fail[now]][i];
q.push(nxt[now][i]);
}
}
} void query(char *s){
int len=strlen(s);
int now=root;
for(int i=;i<len;i++){
now=nxt[now][s[i]-'a'];
//通过pre向上跳
int p=now;
while(p){
q[id[p]].pos.push_back(i);
p=pre[p];
}
} }
}ac; int main(){
ac.init();
scanf("%s",s);
cin>>n;
for(int i=;i<=n;i++){
scanf("%d%s",&q[i].k,buf);
q[i].len=strlen(buf);
ac.insert(buf,i);
}
ac.build();
ac.query(s); //for(int i=1;i<=ac.L;i++)
// cout<<ac.pre[i]<<" "; //处理每个询问
for(int i=;i<=n;i++){
//cout<<q[i].pos.size()<<"\n";
if(q[i].pos.size()<q[i].k){
puts("-1");continue;
} int ans=0x3f3f3f3f;
for(int j=q[i].k-;j<q[i].pos.size();j++){
ans=min(ans,q[i].pos[j]-q[i].pos[j-q[i].k+]+q[i].len);
}
cout<<ans<<'\n';
}
}
/* aaabbbbaaabababab
27
2 aaabbbbaaaba
2 baaabab
1 abbbbaaabab
1 aabbbbaaabab
6 a
1 aaabbbbaaabababab
2 aaba
2 abbbba
5 aa
2 aaabbbb
2 abababa
3 aba
2 baaa
2 bbaaababa
1 aaabab
1 abbb
1 bbbbaaabababa
1 baaab
1 abbbbaaabababa
1 aaababa
1 ababab
2 abb
2 baaabababa
1 bbaaabababa
2 aaabb
1 abababab
4 bab */
ac自动机fail树上按询问建立上跳指针——cf963D的更多相关文章
- CodeForces - 1207G :Indie Album(AC自动机 fail树上DFS)
题意:有N个串,给出的形式是拼接给出,对于第i行: (1,c)表示字符串i是单个字母c: (2,p,c)表示字符串i=在字符串p后面接上一个字母c. 然后给出M个提问,形式是(i,string).问 ...
- AC自动机fail树上dfs序建线段树+动态memset清空
题意:http://acm.hdu.edu.cn/showproblem.php?pid=4117 思路:https://blog.csdn.net/u013306830/article/detail ...
- 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序
3881: [Coci2015]Divljak Time Limit: 20 Sec Memory Limit: 768 MBSubmit: 508 Solved: 158[Submit][Sta ...
- 洛谷2414(构建ac自动机fail树dfs序后遍历Trie树维护bit及询问答案)
要点 这是一道蔡队题,看我标题行事 任意询问y串上有多少个x串,暴力找每个节点是不是结尾肯定是炸的,考虑本质:如果某节点是x的结尾,根据ac自动机的性质,x一定是此(子)串后缀.又有每个Trie节点的 ...
- AC自动机 & Fail树 专题练习
Fail树就是AC自动机建出来的Fail指针构成的树. [bzoj3172][xsy1713]单词 题意 给定一些单词,求每个单词在所有单词里面的出现次数. 分析 构建Fail树,记录每个单词最后一个 ...
- BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)
题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...
- 【bzoj2434-阿狸的打字机】AC自动机+fail树+优化
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23083 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一 ...
- CF 163E. e-Government ac自动机+fail树+树状数组
E. e-Government 题目: 给出n个字符串,表示n个人名,有两种操作: ?string ,统计字符串string中出现的属于城市居民的次数. +id,把编号为id的人变为城市居民,如果已经 ...
- 【学习笔记】ac自动机&fail树
定义 解决文本串和多个模式串匹配的问题: 本质是由多个模式串形成的一个字典树,由tie的意义知道:trie上的每一个节点都是一个模式串的前缀: 在trie上加入fail边,一个节点fail边指向这个节 ...
随机推荐
- hdu 5885 XM Reserves (FFT建模)
Problem Description As an eligible Ingress Resistance Agent you should know your power source, the E ...
- c#如何写服务,打包和卸载服务
Service.cs 每隔一分钟进行一次数据操作 public Service1() { InitializeComponent(); Sy ...
- IDEA @Override is not allowed when implementing interface method(转载)
近期研究idea,在编码过程发现报错:@Override is not allowed when implementing interface method .找到一个老外的回答,感觉挺有用的,记录下 ...
- 【Spring Boot】Spring Boot项目部署到外部Tomcat容器
一.修改项目打包方式为war包 修改pom.xml文件中packaging属性项 <packaging>war</packaging> 修改pom.xml文件增加一个依赖 &l ...
- cs224d 作业 problem set1 (二) 简单的情感分析
使用在上一篇博客中训练好的wordvector 在这一节进行情感分析. 因为在上一节中得到的是一个词就是一个向量 所以一句话便是一个矩阵,矩阵的每一列表示一个词向量 情感分析的前提是已知一句话是 (超 ...
- Redis 单机模式,主从模式,哨兵模式(sentinel),集群模式(cluster),第三方模式优缺点分析
Redis 的几种常见使用方式包括: 单机模式 主从模式 哨兵模式(sentinel) 集群模式(cluster) 第三方模式 单机模式 Redis 单副本,采用单个 Redis 节点部署架构,没有备 ...
- PAT甲级——A1143 LowestCommonAncestor【30】
The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U ...
- idea将springboot项目打成jar包
1.首先,找到pom.xml,把下面的build块中的内容改成如下所示 <build> <plugins> <plugin> <groupId>org. ...
- UVA1595_Symmetry
给出平面上n个点,问你能不能找到一个竖线让他们对称 这道题后面发现真的不难,又不止一种方法 我当时写的很挫,死脑筋的就找一个点的对称点存不存在,用结构体存点信息,在排序用find找,,然后不知道一堆w ...
- jmeter 后台运行 setsid bin/jmeter -n -t .jmx文件 -l .jtl文件
备注: 另外,在Linux下我们有时候希望线程可以在后台运行,这样我们关闭当前连接后,线程依然可以运行,这里提供一个将 jmeter命令设置为后台线程的方法. 使用setsid命令: setsid ...