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. Centos6.5 安装python2.7.14

    2018-06-30 因为Centos6.5系统默认使用,python2.6.6.最近在学python.老师推荐将2.6.6升级至2.7.14.所以以留此文,怕哪天脑子短路好回来看看... >1 ...

  2. MySQL5.7版本安装

    安装方式一: ZIP压缩包安装 >>>首先,到MYSQL官网下载.zip格式的MySQL Server的压缩包,根据需要选择x86或x64版. >>>下载需要登录o ...

  3. laravel自定义返回错误方法

    返回视图传递错误信息 function withInfoErr($msg){ return back()->with('error',$msg); } 返回视图提示消息 function wit ...

  4. Hadoop(6)-HDFS的shell操作

    1.基本语法 使用 hadoop fs 具体命令   或者   hdfs dfs 具体命令 hadoop命令的shell源码 hdfs命令的shell源码 由此可见,这两个命令最后都是执行的一个jav ...

  5. html 弹框 优化 alert

    <!DOCTYPE html> <html> <head> <title>cs</title> </head> <styl ...

  6. 【动态规划】[UVA1025]A Spy in the Metro 城市里的间谍

    参考:https://blog.csdn.net/NOIAu/article/details/71517440 https://blog.csdn.net/c20180630/article/deta ...

  7. Ubuntn14.04安装MATLAB2015b

    一部分转载自:CSDN ,其他结合自己电脑环境配置,旨做备份和记录,同时也提供一个参考. 安装环境: linux Ubuntu14.04 (x64) 软件包下载地址: Matlab R2015b_gl ...

  8. ionic打包apkFailed to execute shell command "input,keyevent,82"" on device: Error: adb: Command failed with exit code 137

    错误代码如下 BUILD SUCCESSFUL in 12s 46 actionable tasks: 1 executed, 45 up-to-date Built the following ap ...

  9. ubuntu apt-get 使用代理设置,坑爹。。

    网上流传的export http_proxy=http://yourproxyaddress:proxyport是行不通的,虽然改了之后wget一类的可以用.当然去改.bashrc也不会有效果. 真正 ...

  10. Android中通过拨号调起应用的实现方式及特殊情况处理

    Android中有时我们会有这样的需求:通过拨号调起我们的程序.这个需求如何实现呢? 思路当然是在我们的应用中实现一个广播接收器(BroadcastReceiver),对打电话时系统发出的广播进行拦截 ...