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 自动机)的更多相关文章

  1. fzu 2128 AC自动机

    链接   http://acm.fzu.edu.cn/problem.php?pid=2128 解题方法  首先考虑暴力,,就是拿每一个字符串在匹配串里面找到所有位置,然后从头到尾不断更新最长的合理位 ...

  2. 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 ...

  3. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  4. AC自动机-算法详解

    What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...

  5. python爬虫学习(11) —— 也写个AC自动机

    0. 写在前面 本文记录了一个AC自动机的诞生! 之前看过有人用C++写过AC自动机,也有用C#写的,还有一个用nodejs写的.. C# 逆袭--自制日刷千题的AC自动机攻克HDU OJ HDU 自 ...

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

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

  7. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

  8. BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]

    1212: [HNOI2004]L语言 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1367  Solved: 598[Submit][Status ...

  9. [AC自动机]【学习笔记】

    Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)To ...

随机推荐

  1. over开窗函数的用法

    over(partition by c1.pmid,d1.type,e1.objid  order by e1.objid ) pinum 先根据字段排序,pinum.在取第一条数据and p1.pi ...

  2. ECSHOP快递单号查询插件圆通V8.2专版

    本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅急送快递.德邦物流.百世快递.汇通快递.中通快递.天天快递等知 ...

  3. [转]App离线本地存储方案

    App离线本地存储方案 原文地址:http://ask.dcloud.net.cn/article/166 HTML5+的离线本地存储有如下多种方案:HTML5标准方案:cookie.localsto ...

  4. scala成长之路(5)问题记录

    还是在看scala sdk源码的时候,有很多问题要考自己慢慢摸索,这里做个记录. 一. 隐式转换的作用域? 隐式转换需要三个因素 1. 己方(当前对象) 2. 转换函数 3. 对方(转换的目标类) 这 ...

  5. GET TIME

    基本形式 GET TIME [FIELD tim]. オプション: ... FIELD tim 機能 FIELD オプションを使用しない場合. 日付および時刻のシステム項目 sy-datlo.sy-d ...

  6. 查询如下课程平均成绩和及格率的百分数(用"1行"显示): 企业管理(001),马克思(002),OO&UML (003),数据库(004)

    SELECT SUM(CASE WHEN C# ='001' THEN score ELSE 0 END)/SUM(CASE C# WHEN '001' THEN 1 ELSE 0 END) AS 企 ...

  7. 【转】Git远程操作详解

    Git是目前最流行的版本管理系统,学会Git几乎成了开发者的必备技能. Git有很多优势,其中之一就是远程操作非常简便.本文详细介绍5个Git命令,它们的概念和用法,理解了这些内容,你就会完全掌握Gi ...

  8. malloc函数分配失败处理的严重性

    本次在实际测试情况下,发现程序无缘无故的异常,导致看门狗超时复位,经过排查是malloc函数分配失败的时候,依然对指针进行了操作,导致异常.以前没重视这个问题是因为,总觉的malloc基本都会成功的, ...

  9. jmeter上传视频图片附件

    http上传附件一般用的Content-Type: multipart/form-data;文中是先通过fiddler抓取手机端的请求,然后通过jmeter模拟该请求,如果有接口文档,则可以跳过抓包这 ...

  10. FJOI 2019 游记

    (FJOI 2019 滚粗记) Day 0 早上刷了一些水题,然后就上路了. (画图3D好好玩) 来得晚只有十几分钟时间看考场,于是连试机题都没有Ak. Day 1 果然我还是太菜了 走过来的时候再讨 ...