建个SAM,符合要求的串显然是|right|1的节点多代表的串,设si[i]为right集合大小,p[i]为right最大的r点,这些都可以建出SAM后再parent树上求得

然后对弈si[i]1的点,考虑它所代表的串是s(p[i]-dis[i]+1,p[i])~s(p[i]-dis[fa[i]],p[i]),然后对于p[i]-dis[i]+1<=x<=p[i]-dis[fa[i]],对x的答案的贡献是p[i]-x+1,带着-x不好做所以最后再-x,也就是贡献p[i]+1;对于p[i]-dis[fa[i]]<=x<=p[i],贡献是dis[fa[i]]+1(因为再小就重复了),所以建两棵线段树分别存两种贡献,最后取min即可

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=200005;
int n,fa[N],ch[N][27],dis[N],con=1,cur=1,la,p[N],c[N],a[N],si[N];
char s[N];
struct xds
{
int l,r,mn,lz;
};
struct wk
{
xds t[N<<2];
void pd(int ro)
{
if(t[ro].lz!=1e9)
{
t[ro<<1].mn=min(t[ro<<1].mn,t[ro].lz);
t[ro<<1].lz=min(t[ro<<1].lz,t[ro].lz);
t[ro<<1|1].mn=min(t[ro<<1|1].mn,t[ro].lz);
t[ro<<1|1].lz=min(t[ro<<1|1].lz,t[ro].lz);
t[ro].lz=1e9;
}
}
void build(int ro,int l,int r)
{
t[ro].l=l,t[ro].r=r,t[ro].mn=1e9,t[ro].lz=1e9;
if(l==r)
return;
int mid=(l+r)>>1;
build(ro<<1,l,mid);
build(ro<<1|1,mid+1,r);
}
void update(int ro,int l,int r,int v)
{
if(t[ro].l==l&&t[ro].r==r)
{
t[ro].mn=min(t[ro].mn,v);
t[ro].lz=min(t[ro].lz,v);
return;
}
pd(ro);
int mid=(t[ro].l+t[ro].r)>>1;
if(r<=mid)
update(ro<<1,l,r,v);
else if(l>mid)
update(ro<<1|1,l,r,v);
else
update(ro<<1,l,mid,v),update(ro<<1|1,mid+1,r,v);
t[ro].mn=min(t[ro<<1].mn,t[ro<<1|1].mn);
}
int ques(int ro,int p)
{
if(t[ro].l==t[ro].r)
return t[ro].mn;
pd(ro);
int mid=(t[ro].l+t[ro].r)>>1;
if(p<=mid)
return ques(ro<<1,p);
else
return ques(ro<<1|1,p);
}
}t1,t2;
void ins(int c,int id)
{
la=cur,dis[cur=++con]=id,p[cur]=id,si[cur]=1;
int p=la;
for(;p&&!ch[p][c];p=fa[p])
ch[p][c]=cur;
if(!p)
fa[cur]=1;
else
{
int q=ch[p][c];
if(dis[q]==dis[p]+1)
fa[cur]=q;
else
{
int nq=++con;
dis[nq]=dis[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];
fa[q]=fa[cur]=nq;
for(;ch[p][c]==q;p=fa[p])
ch[p][c]=nq;
}
}
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;i++)
ins(s[i]-'a',i);
t1.build(1,1,n),t2.build(1,1,n);
for(int i=1;i<=con;i++)
c[dis[i]]++;
for(int i=1;i<=n;i++)
c[i]+=c[i-1];
for(int i=1;i<=con;i++)
a[c[dis[i]]--]=i;
for(int i=con;i>=1;i--)
si[fa[a[i]]]+=si[a[i]],p[fa[a[i]]]=max(p[fa[a[i]]],p[a[i]]);
// for(int i=1;i<=con;i++)
// cerr<<si[i]<<" "<<p[i]<<endl;
for(int i=1;i<=con;i++)
if(si[i]==1)
t1.update(1,p[i]-dis[i]+1,p[i]-dis[fa[i]],p[i]+1),t2.update(1,p[i]-dis[fa[i]],p[i],dis[fa[i]]+1);
for(int i=1;i<=n;i++)
printf("%d\n",min(t1.ques(1,i)-i,t2.ques(1,i)));
return 0;
}

bzoj 1396: 识别子串【SAM+线段树】的更多相关文章

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

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

  2. BZOJ 1396:识别子串 SA+树状数组+单调队列

    1396: 识别子串 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 381  Solved: 243[Submit][Status][Discuss] ...

  3. BZOJ.1396.识别子串(后缀自动机/后缀数组 线段树)

    题目链接 SAM:能成为识别子串的只有那些|right|=1的节点代表的串. 设这个节点对应原串的右端点为r[i],则如果|right[i]|=1,即\(s[\ [r_i-len_i+1,r_i-le ...

  4. bzoj 1396 识别子串 后缀树+线段树

    题目大意 给定一个长度\(\le100000\)的字符串 求每一个位置的最短识别子串 对于位置\(x\),能识别子串\(s[i...j]\)的条件是 1.\(i\le x \le j\) 2.\(s[ ...

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

    手动博客搬家: 本文发表于20181221 00:58:26, 原地址https://blog.csdn.net/suncongbo/article/details/85150962 嗯,以后博客内容 ...

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

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

  7. bzoj 1396: 识别子串 && bzoj 2865: 字符串识别【后缀数组+线段树】

    根据height数组的定义,和当前后缀串i最长的相同串的长度就是max(height[i],height[i+1]),这个后缀贡献的最短不同串长度就是len=max(height[i],height[ ...

  8. ●BZOJ 1396 识别子串

    题链: http://www.joyoi.cn/problem/tyvj-2301(非权限OI患者,苟且在joyoi...)题解: 后缀自动机,线段树 先对原串建立后缀自动机,不难发现, 会影响答案是 ...

  9. 5.29 省选模拟赛 波波老师 SAM 线段树 单调队列 并查集

    LINK:波波老师 LINK:同bzoj 1396 识别子串 不过前者要求线性做法 后者可以log过.实际上前者也被我一个log给水过了. 其实不算很水 我自认跑的很快罢了. 都是求经过一个位置的最短 ...

随机推荐

  1. gulp配置 - PC

    初始化目录结构如下(图片看不清可以拖到桌面或者直接CTRL+鼠标滚轮进行观看) 开发环境示例: 上线环境示例: gulpfile.js(详解版) (2018-3-28)添加了scss处理(去除了les ...

  2. android menu事件

    @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0,1,1,R.string.exit); menu.add(0, ...

  3. 关于 underscore 中模板引擎的应用演示样例

    //关于 underscore 中模板引擎的应用演示样例 <!doctype html> <html> <head> <meta charset=" ...

  4. ios自动生成对象类,提高开发速率

    #import "autoGenerationFileUtility.h" @implementation autoGenerationFileUtility - (void)cr ...

  5. POJ 2524 Ubiquitous Religions (幷查集)

    Ubiquitous Religions Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 23090   Accepted:  ...

  6. 记录魅族m1note编译TWRP recovery 3.1.0-0,包括mtk机型的处理方法

    1.安装64位linux系统,我用的是deepin os 15.3 2.将系统升级到最新版本 sudo apt-get update && sudo apt-get upgrade 3 ...

  7. 翻译:A Tutorial on the Device Tree (Zynq) -- Part IV

    获取资源信息 内核模块驱动加载之后,就开始把硬件资源管理起来,如读写寄存器.接收中断. 来看看设备树里的一条: xillybus_0: xillybus@50000000 { compatible = ...

  8. [Android]Android5.0实现静默接听电话功能

    原因: android曾经能够通过AIDL进行静默接听.可是5.0以后就被谷歌给屏蔽了.这时候我们仅仅能通过其它方式实现了. 解决方式: try { Runtime.getRuntime().exec ...

  9. querying rpm database

    Call dbMatch on a transaction set to create a match iterator. As with the C API, a match iterator al ...

  10. vmware nat不能上网的解决办法

    1 很多奇怪的问题都是vmware突然不能上网导致的 当yum.pip等包管理工具突然不能上网了时,要ping www.baidu.com,看看网络是不是好的. 2 nat网络出现问题的解决办法 2. ...