fzu 2246(ac 自动机)
fzu 2246(ac 自动机)
题意:
某一天YellowStar学习了AC自动机,可以解决多模式匹配问题。YellowStart当然不会满足于此,它想进行更深入的研究。
YellowStart有一个母串\(S\),以及\(m\)个询问串\(T\),它发现如果把母串删除掉一个子串,把剩余的串按原先顺序拼接起来,某些询问串\(T\)就可能出现在这个新的母串中。
现在,对于第\(i\)个询问串\(T_i\),YellowStar想知道,母串最多可以删除多长的子串,使得该询问串出现在新的母串的子串中。
\(|S| <= 1e5\)
$\sum{|T_i|} <= 1e5 $
思路:利用ac自动机处理出每个查询串的每个前缀在S中最先出现的位置 和 每个后缀在S中最后出现的位置,取
\(max(sufpos[i+1] - prepos[i] - 1)\)即可
具体的做法 是将所有询问串 正着一遍插入ac自动机,对于串S 类似于找子串的方式更新当前位置匹配的所有前缀,然后再反着插入做一遍即可
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#define LL long long
using namespace std;
const int N = 1e5 + 10;
char S[N],P[N],tmp[N],S_r[N];
int m, tot;
int len[N],st[N];
int pre_id[N],suf_id[N];
int pre_pos[N],suf_pos[N];
const int SIZE = 26;
const int MAXNODE = 1e5 + 10;
struct AC{
int ch[MAXNODE][SIZE];
int f[MAXNODE],last[MAXNODE],val[MAXNODE];
int sz;
void init(){sz = 1;memset(ch[0],0,sizeof(ch[0]));}
int idx(char c){return c - 'a';}
int _insert(char *s, int st,int len,int *p){
int u = 0;
for(int i = 0;i < len;i++){
int c = idx(s[i + st]);
if(!ch[u][c]){
memset(ch[sz],0,sizeof ch[sz]);
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
val[u] = 1;
p[i + st] = u;
}
return u;
}
void getFail(){
queue<int> q;
f[0] = 0;
for(int c = 0;c < SIZE;c++){
int u = ch[0][c];
if(u){
f[u] = 0;
q.push(u);
last[u] = 0;
}
}
while(!q.empty()){
int r = q.front();q.pop();
for(int c = 0;c < SIZE;c++){
int u = ch[r][c];
if(!u){ch[r][c] = ch[f[r]][c];continue;}
q.push(u);
int v = f[r];
while(v && !ch[v][c]) v = f[v];
f[u] = ch[v][c];
last[u] = val[f[u]]?f[u]:last[f[u]];
}
}
}
void up(int u,int x,int *p){
if(!u) return ;
if(p[u] == -2) p[u] = x;
up(last[u],x,p);
}
void Find(char *s,int *p){
int len = strlen(s), u = 0;
pre_pos[u] = -1;
for(int i = 0;i < len;i++){
int c = idx(s[i]);
u = ch[u][c];
up(u,i,p);
}
}
}ac;
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%s",P);
scanf("%d",&m);
tot = 0;
for(int i = 0;i < m;i++){
scanf("%s",tmp);
len[i] = strlen(tmp);
st[i] = tot;
for(int j = 0;j < len[i];j++) S[j + tot] = tmp[j];
reverse(tmp,tmp + len[i]);
for(int j = 0;j < len[i];j++) S_r[j + tot] = tmp[j];
tot += len[i];
}
for(int i = 0;i < tot;i++) pre_pos[i] = suf_pos[i] = -2;
ac.init();
for(int i = 0;i < m;i++) ac._insert(S,st[i],len[i],pre_id);
ac.getFail();
ac.Find(P,pre_pos);
ac.init();
for(int i = 0;i < m;i++) ac._insert(S_r,st[i],len[i],suf_id);
ac.getFail();
int tlen = strlen(P);
reverse(P,P + tlen);
ac.Find(P,suf_pos);
for(int i = 0;i < m;i++){
int ans = -1;
int stt = st[i],ll = len[i];
if(pre_pos[pre_id[stt + ll - 1]] != -2) ans = max(ans, tlen - pre_pos[pre_id[stt + ll - 1]] - 1);
if(suf_pos[suf_id[stt + ll - 1]] != -2) ans = max(ans, tlen - suf_pos[suf_id[stt + ll - 1]] - 1);
for(int j = 0;j + 1 < ll;j++){
int a = pre_pos[pre_id[j + stt]];
int b = suf_pos[suf_id[ll - j - 2 + stt]];
if(a != -2 && b != -2 && tlen - b -1 - a - 1 >= 1) ans = max(ans,tlen - b - 1 - a - 1);
}
printf("%d\n",ans);
}
}
return 0;
}
fzu 2246(ac 自动机)的更多相关文章
- fzu 2128 AC自动机
链接 http://acm.fzu.edu.cn/problem.php?pid=2128 解题方法 首先考虑暴力,,就是拿每一个字符串在匹配串里面找到所有位置,然后从头到尾不断更新最长的合理位 ...
- HDU 3341 Lost's revenge AC自动机+dp
Lost's revenge Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)T ...
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
- AC自动机-算法详解
What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...
- python爬虫学习(11) —— 也写个AC自动机
0. 写在前面 本文记录了一个AC自动机的诞生! 之前看过有人用C++写过AC自动机,也有用C#写的,还有一个用nodejs写的.. C# 逆袭--自制日刷千题的AC自动机攻克HDU OJ HDU 自 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]
3172: [Tjoi2013]单词 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3198 Solved: 1532[Submit][Status ...
- BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]
1212: [HNOI2004]L语言 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1367 Solved: 598[Submit][Status ...
- [AC自动机]【学习笔记】
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)To ...
随机推荐
- Idea 2017 激活方法
http://www.cnblogs.com/suiyueqiannian/p/6754091.html
- hive 学习系列二(数据库的创建删除修改) 拿走,不谢。
database 相当于一个目录或者命名空间,用来更好地进行表的管理 在hdfs 的目录位置大致如下: [root@iZbp12vtv76y9q3d633bh6Z /]# hadoop fs -ls ...
- Python的scrapy之爬取boss直聘网站
在我们的项目中,单单分析一个51job网站的工作职位可能爬取结果不太理想,所以我又爬取了boss直聘网的工作,不过boss直聘的网站一次只能展示300个职位,所以我们一次也只能爬取300个职位. jo ...
- POJ-2421-Constructing Roads(最小生成树 普利姆)
Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 26694 Accepted: 11720 Description The ...
- MongoDB从环境搭建到代码编程(Window 环境)
本人开发环境: window Server 2008 , 64位系统 服务端 MongoDB下载地址:http://www.mongodb.org/downloads (本人己下好的在百度网盘 : ...
- springboot升级到2.x需要改动的地方
由于需要跟进技术发展的脚步,对原有项目springboot进行2.0升级,但升级并不是说改一下版本就完事了,springboot2.0变动比较多,详细变化可以百度一下,下面针对升级springboot ...
- spring、spring-data-redis整合使用
一.Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 从2010年3月15日起,Redis的开发工作由VMwa ...
- pprof 查看goroutine
package main import ( "net/http" "runtime/pprof" ) var quit chan struct{} = make ...
- 简单工具 & 杂技
图片压缩: 腾讯智图(http://zhitu.isux.us/) 手机的所有尺寸大小规范: http://screensiz.es/phone 需求: 移动端宽高一致的盒子(因为移动端屏幕宽度不一样 ...
- Ngix配置,让所有请求指向同一个文件
统一入口使所有请求在同一个文件先验证处理,Ngix添加如下代码: location / { try_files '' /index.php; }