https://www.lydsy.com/JudgeOnline/problem.php?id=1396

后缀自动机的parent树上,如果不是叶子节点,那么至少有两个子节点

而一个状态所代表子串的出现次数就是子树中叶子节点的个数

所以只有叶子节点 即 |Right|=1的状态 代表的子串 出现了1次

我们计算以每一个位置为子串右端点时,它对一些位置的贡献

枚举|Right|=1的状态s

令end=Right(s)

那么以end为子串右端点,长度在[1,Max(parent(s))]的子串至少还会在s的父节点表示的状态中出现

所以在以end为识别子串右端点时

位置[end-Max(parent(s)),end]的最短长度为Max(parent(s)+1

位置[end-Max(s)+1,end-Max(parent(s))]的最短长度为 end-i+1

用两棵线段树维护

一棵直接维护最小值

另一棵维护end+1的最小值,查询的时候将结果-i

#include<cstdio>
#include<cstring>
#include<algorithm> #define N 100001 using namespace std; char s[N]; int ch[N<<][],tot=;
int fa[N<<],len[N<<];
int siz[N<<];
int last=,p,q,np,nq; int leaf[N]; int v[N],sa[N<<]; struct Segment
{
int mx[N<<];
int tag[N<<]; void down(int k)
{
mx[k<<]=min(mx[k<<],tag[k]);
mx[k<<|]=min(mx[k<<|],tag[k]);
tag[k<<]=min(tag[k<<],tag[k]);
tag[k<<|]=min(tag[k<<|],tag[k]);
tag[k]=2e9;
} void build(int k,int l,int r)
{
mx[k]=tag[k]=2e9;
if(l==r) return;
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
} void change(int k,int l,int r,int opl,int opr,int w)
{
if(l>=opl && r<=opr)
{
mx[k]=min(mx[k],w);
tag[k]=min(tag[k],w);
return;
}
int mid=l+r>>;
if(tag[k]!=2e9) down(k);
if(opl<=mid) change(k<<,l,mid,opl,opr,w);
if(opr>mid) change(k<<|,mid+,r,opl,opr,w);
mx[k]=min(mx[k<<],mx[k<<|]);
} int query(int k,int l,int r,int x)
{
if(l==r) return mx[k];
int mid=l+r>>;
if(tag[k]!=2e9) down(k);
if(x<=mid) return query(k<<,l,mid,x);
return query(k<<|,mid+,r,x);
}
}; Segment tr1,tr2; void extend(int c)
{
len[np=++tot]=len[last]+;
siz[tot]=;
for(p=last;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=;
else
{
q=ch[p][c];
if(len[q]==len[p]+) fa[np]=q;
else
{
nq=++tot;
fa[nq]=fa[q];
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[q]=fa[np]=nq;
len[nq]=len[p]+;
for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
}
}
last=np;
} int main()
{
scanf("%s",s+);
int n=strlen(s+);
for(int i=;i<=n;++i)
{
leaf[i]=tot+;
extend(s[i]-'a');
}
for(int i=;i<=tot;++i) v[len[i]]++;
for(int i=;i<=n;++i) v[i]+=v[i-];
for(int i=;i<=tot;++i) sa[v[len[i]]--]=i;
int x;
for(int i=tot;i;--i)
{
x=sa[i];
siz[fa[x]]+=siz[x];
}
tr1.build(,,n);
tr2.build(,,n);
int l,r,end;
for(int x=;x<=tot;++x)
if(siz[x]==)
{
l=len[fa[x]];
r=len[x];
end=len[x];
tr1.change(,,n,end-l,end,l+);
tr2.change(,,n,end-r+,end-l,end+);
}
int a,b;
for(int i=;i<=n;++i)
{
a=tr1.query(,,n,i);
b=tr2.query(,,n,i)-i;
printf("%d\n",min(a,b));
}
return ;
}

bzoj千题计划318:bzoj1396: 识别子串(后缀自动机 + 线段树)的更多相关文章

  1. BZOJ1396: 识别子串(后缀自动机 线段树)

    题意 题目链接 Sol 后缀自动机+线段树 还是考虑通过每个前缀的后缀更新答案,首先出现次数只有一次,说明只有\(right\)集合大小为\(1\)的状态能对答案产生影响 设其结束位置为\(t\),代 ...

  2. BZOJ 1396&&2865 识别子串[后缀自动机 线段树]

    Description 在这个问题中,给定一个字符串S,与一个整数K,定义S的子串T=S(i, j)是关于第K位的识别子串,满足以下两个条件: 1.i≤K≤j. 2.子串T只在S中出现过一次. 例如, ...

  3. bzoj1396&&2865 识别子串 后缀自动机+线段树

    Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. Sample Input agoodco ...

  4. 【BZOJ1396】识别子串 - 后缀自动机+线段树

    题意: Description Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. 题解: ...

  5. BZOJ 1396 识别子串 (后缀自动机+线段树)

    题目大意: 给你一个字符串S,求关于每个位置x的识别串T的最短长度,T必须满足覆盖x,且T在S中仅出现一次 神题 以节点x为结尾的识别串,必须满足它在$parent$树的子树中只有一个$endpos$ ...

  6. bzoj千题计划311:bzoj5017: [Snoi2017]炸弹(线段树优化tarjan构图)

    https://www.lydsy.com/JudgeOnline/problem.php?id=5017 暴力: 对于每一个炸弹,枚举所有的炸弹,看它爆炸能不能引爆那个炸弹 如果能,由这个炸弹向引爆 ...

  7. bzoj 1396/2865: 识别子串 后缀自动机+线段树

    水水的字符串题 ~ #include <map> #include <cstdio> #include <cstring> #include <algorit ...

  8. bzoj1396识别子串(SAM+线段树)

    复习SAM板子啦!考前刷水有益身心健康当然这不是板子题/水题…… 很容易发现只在i位置出现的串一定是个前缀串.那么对答案的贡献分成两部分:一部分是len[x]-fa~len[x]的这部分贡献会是r-l ...

  9. BZOJ 1396: 识别子串( 后缀数组 + 线段树 )

    这道题各位大神好像都是用后缀自动机做的?.....蒟蒻就秀秀智商写一写后缀数组解法..... 求出Height数组后, 我们枚举每一位当做子串的开头. 如上图(x, y是height值), Heigh ...

随机推荐

  1. 【CF768G】The Winds of Winter 可持久化线段树 DFS序

    题目大意 给定一棵\(n\)个点的树,对于树上每个结点,将它删去,然后可以将得到的森林中任意一个点与其父亲断开并连接到另一颗树上,对每一个点求出森林中所有树\(size\)最大值的最小值. \(n\l ...

  2. @ResponseBody注解

    作用 @ResponseBody注解表示该方法的返回结果直接写入HTTP response body中 原理 在使用此注解之后跳过视图处理器,将返回的对象通过适当的转换器转换为指定的格式之后,直接将数 ...

  3. mysql 0x80004005 unable to connect to any of the specified mysql hosts

    语言:c# 问题:偶尔会出现连不上mysql 报标题的这个错误. 解决方法:把server = localhost 改为 =127.0.0.1 或者静态IP  ,按着改暂时没出现了,继续观望!

  4. 「POJ - 1003」Hangover

    BUPT 2017 summer training (16) #2C 题意 n个卡片可以支撑住的长度是1/2+1/3+1/4+..+1/(n+1)个卡片长度.现在给出需要达到总长度,求最小的n. 题解 ...

  5. 【BZOJ4784】[ZJOI2017]仙人掌(Tarjan,动态规划)

    [BZOJ4784][ZJOI2017]仙人掌(Tarjan,动态规划) 题面 BZOJ 洛谷 题解 显然如果原图不是仙人掌就无解. 如果原图是仙人掌,显然就是把环上的边给去掉,变成若干森林连边成为仙 ...

  6. 「浙大ACM」图森未来杯游记一篇以及简易口胡题解

    前言 蒟蒻有参加了ACM比赛,这一次有适合HY和慕容宝宝大佬一起比的,他们好巨啊,把我带飞了. 又是窝掌机,QAQ,他们仗着自己巨,就欺负窝... 我又打了\(4\)个小时的代码,而且那个键盘太恶心了 ...

  7. 0-1背包 VIOJ1025

    P1025小飞侠的游园方案 请 登录 后递交 标签:[显示标签] 描述 菜虫:你的题目是--我们的情报组织探听到敌人的重要将领--小飞侠星期天会邀他的灵儿妹妹到公园去玩.公园里有很多娱乐项目,可并不是 ...

  8. bzoj3796(后缀数组)(SA四连)

    bzoj3796Mushroom追妹纸 题目描述 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从 ...

  9. django rest framework mixins

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAXQAAAEZCAIAAAAIa0mAAAAU/0lEQVR4nO2d247cxoGG5y3yKH6AAf

  10. Ubuntu16.04下的NetCore环境搭建(附录含Ubuntu 18.04 安装 NetCore2.1)

    跨平台系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#linux VSCode安装:http://www.cnblogs.com/dunitia ...