题面

传送门

思路

首先,我们观察一下这个要求的“模板串”,发现它有如下性质:

1.一个模板串$A$是要求的文本串$B$的公共前后缀

2.如果一个模板串$A$有另一个模板串$B$(也就是$B$可以覆盖A),那么$B$是比$A$更优的一个解

3.如果模板串$A$可以完全覆盖文本串$B$,那么$A$在$B$中的匹配位置(按照开头算)之间的空格数不会超过$A$的长度

这三条性质都挺明显的是吧?接下来我们就看看我们能怎么利用它

如何利用性质一?

性质一告诉我们,我们可以把文本串的$next$数组(就是$KMP$里面那个)求出来,然后做这样的操作:

i=n;//n=strlen(文本串)
while(i) s[++top]=i,i=next[i];

做完这个操作以后栈$s$中就存放了所有可能的模板串长度

如何利用性质二?

我们从小到大枚举$s$中的模板串,对于每个模板串,如果它满足性质三,就令这个长度为答案,否则就再增长一点

同时,我们有一个结论:能被/长度比较长的/符合性质一的/模板串(对于原串满足)/满足性质一的/一个前缀(这个前缀作为文本串满足)/,一定能和/长度比它短的/另一个模板串(此处也是作为文本串)/满足性质一(这句话意思比较绕)

如何利用性质三?

我们构建一个链表(双向的),只包含删除操作和求最大空隙操作,那么它的每个操作是$O\left(1\right)$的

那么我们一开始把文本串的所有位置插入链表,每一次更新上一个长度的模板串能满足性质一的、但是当前长度的模板串不能满足性质一的字符位置(也就是把那个点从链表里面删掉),维护最大空隙

当一个模板串满足性质三的时候,它就是答案了(因为我们是从小到大枚举的,而题目要求最短的那个)

还剩什么问题?

我们最后剩下一个问题:如何把匹配$s[i+1]$代表的模板串、但是不匹配$s[i]$代表的模板串的位置找出来?

这里我们要利用一个新的数据结构(可能不算?),就是$fail$树(也称$next$树)

$fail$树就是把$fail[i]$(为了方便,以后$next[i]$称作$fail[i]$)和$i$连起来形成的树,以0为根节点

$fail$树有这样的性质:

1.点$x$如果是点$y$的祖先,那么$y$代表的前缀的一个公共前后缀为$x$代表的前缀

2.不在同一子树内的两点代表的前缀不能互相满足性质一

那么,我们发现,这道题的问题,其实就是从根节点开始往n号节点走一条链,并且每次把当前节点的$fail$树子树中的所有节点标记,统计原串上的最大空隙,如果空隙小于当前节点代表的前缀的长度,就作为答案输出

所以实际上这是个fail树的题目

好像不用fail也能做?反正本蒟蒻是想不出来......

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char a[500010];int n,cnt,maxgap,fail[500010],pre[500010],suc[500010],first[500010],ans[500010],tot;
struct edge{//fail树上的边
int to,next;
}e[500010];
void add(int u,int v){
e[++cnt]=(edge){v,first[u]};first[u]=cnt;
}
void getfail(){//求next数组(我的代码里叫fail)
int i,j=0;
for(i=1;i<n;i++){
while(j&&(a[i]!=a[j])) j=fail[j];
j+=(a[i]==a[j]);fail[i+1]=j;
}
for(i=1;i<=n;i++) add(fail[i],i);
}
void del(int x){//链表删除操作,O(1)
suc[pre[x]]=suc[x];
pre[suc[x]]=pre[x];
maxgap=max(maxgap,suc[x]-pre[x]);suc[x]=pre[x]=0;
}
int q[500010];
void bfs(int s,int avoid){//s的子树中,避开avoid的子树,其余点全部从链表里面删掉
int u,v,i,head=0,tail=1;q[0]=s;
while(head<tail){
u=q[head++];if(u==avoid) continue;
del(u);
for(i=first[u];~i;i=e[i].next){
v=e[i].to;q[tail++]=v;
}
}
}
int main(){
memset(first,-1,sizeof(first));memset(fail,0,sizeof(fail));int i,j;
scanf("%s",a);n=strlen(a);
getfail();
for(i=n;i;i=fail[i]) ans[++tot]=i;ans[tot+1]=0;
for(i=1;i<=n;i++) pre[i]=i-1,suc[i]=i+1;
maxgap=1;
for(i=tot;i>=1;i--){
bfs(ans[i+1],ans[i]);
if(maxgap<=ans[i]){
printf("%d",ans[i]);return 0;
}
}
}

[POI2005][luogu3462] SZA-Template [fail树]的更多相关文章

  1. LG5357 「模板」AC自动机(二次加强版) AC自动机+fail树

    问题描述 LG5357 题解 不是fail树的AC自动机复杂度是假的. 把AC自动机搞出来,建立Trie树,树上爆搜一遍就好了. \(\mathrm{Code}\) #include<bits/ ...

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

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

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

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

  4. fail树

    前置技能:AC自动机 假设我们有了一个AC自动机,然后在上面进行字符串匹配. 上面是一个有四个字符串的AC自动机(abcde.aacdf.cdf.cde),虚线是fail指针,实线是转移. 这是上一次 ...

  5. 【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组

    E. e-Government time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...

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

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

  7. 【BZOJ 2434】【NOI 2011】阿狸的打字机 fail树

    完全不会啊,看题解还看了好久,我是蒟蒻$QAQ$ $zyf$的题解挺好的:http://blog.csdn.net/clove_unique/article/details/51059425 $fai ...

  8. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

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

  9. 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组

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

随机推荐

  1. 感知器及其Python实现

    感知器是由美国计算机科学家罗森布拉特(F.Roseblatt)于1957年提出的.感知器可谓是最早的人工神经网络.单层感知器是一个具有一层神经元.采用阈值激活函数的前向网络.通过对网络权值的训练,可以 ...

  2. 常量池与方法区以及又读new String对象创建问题

    又拿出这道String str1 = new String("abc");创建几个对象的面试题梳理了一下常量池与方法区的关系,希望能把这两者的关系通过这道面试题说明白 方法区是什么 ...

  3. 更改 Linux 语言为中文

    查看当前系统语言环境:    echo $LANG 查看安了哪些中文语言包    locale -a |grep "zh_CN" 没有输出,说明没有安装,输入下面的命令安装     ...

  4. Mysql--7种Join查询

    0.sql的执行顺序 手写顺序 机读顺序 总结 ①From:对from左边的表和右边的表计算笛卡尔积,产生虚拟表c1 ②On:对c1中的数据进行on过滤,只有符合过滤条件的数据记录才会记录在虚拟表c2 ...

  5. keepalived原理(主从配置+haproxy)及配置文件详解

    下图描述了使用keepalived+Haproxy主从配置来达到能够针对前段流量进行负载均衡到多台后端web1.web2.web3.img1.img2.但是由于haproxy会存在单点故障问题,因此使 ...

  6. 小象学院Python数据分析第二期【升级版】

    点击了解更多Python课程>>> 小象学院Python数据分析第二期[升级版] 主讲老师: 梁斌 资深算法工程师 查尔斯特大学(Charles Sturt University)计 ...

  7. 致敬wusir懒孩子自有懒孩子的生存之道之二

    https://www.cnblogs.com/wupeiqi/ https://www.cnblogs.com/Eva-J/ https://www.cnblogs.com/wupeiqi/p/90 ...

  8. mysql密码正确却提示错误, 不输入密码反而能登录

    今天部署阿里云服务器, 发现之前可以连接的mysql服务器突然连接不上了, 密码我确认是正确的,但登录时就是显示密码错误, 很崩溃, 差点气得我就想重装mysql了. 好在经过几番苦寻找到了以下能解决 ...

  9. Paper Folding UVA - 177 模拟+思路+找规律

    题目:题目链接 思路:1到4是很容易写出来的,我们先考虑这四种情况的绘制顺序 1:ru 2:rulu 3:rululdlu 4:rululdluldrdldlu 不难发现,相较于前一行,每一次增加一倍 ...

  10. 2018年湘潭大学程序设计竞赛 E 吃货

    题目描述 作为一个标准的吃货,mostshy又打算去联建商业街觅食了.混迹于商业街已久,mostshy已经知道了商业街的所有美食与其价格,而且他给每种美食都赋予了一个美味度,美味度越高表示他越喜爱这种 ...