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

Input
Output
Sample Input
Sample Output
2
3
3
2
2
3
3
2
2
3
3
2
1
2
3
3
2
1
2
3
4
理解起来就是对于[endpos−maxlen+1,endpos−minlen+1][endpos−maxlen+1,endpos−minlen+1]中的每个子串都是单独存在的,所以这个RightRight集合贡献给他的答案就是这个点到endposendpos的长度。
对于[endpos−minlen,endpos][endpos−minlen,endpos]中的每个位置xx,贡献就是minlenminlen;
理解起来就是对于[endpos−minlen,endpos][endpos−minlen,endpos]中的每个子串显然是存在多个结束位置的,所以当前这个RightRight集合能够贡献给他的符合只出现一次且最短的,就是刚好跨过它的最小,即minlenminlen。
对于2865数据范围大了,而且还卡内存,不要面孔
纯自己手打
#pragma GCC optimize(2)
#pragma G++ optimize(2)
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio> #define inf 1000000007
#define N 200007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n;
char ch[N]; struct segment_tree
{
int tree[N<<];
inline void push_down(int p,int l,int r)
{
if(l==r)return;
int ls=p<<,rs=p<<|;
tree[ls]=min(tree[ls],tree[p]);
tree[rs]=min(tree[rs],tree[p]);
}
void update(int p,int l,int r,int x,int y,int num)
{
if(x>y)return;
push_down(p,l,r);
if(l==x&&y==r)
{
tree[p]=min(tree[p],num);
return;
}
int mid=(l+r)>>;
if(y<=mid)update(p<<,l,mid,x,y,num);
else if(x>mid)update(p<<|,mid+,r,x,y,num);
else update(p<<,l,mid,x,mid,num),update(p<<|,mid+,r,mid+,y,num);
}
void build(int p,int l,int r)
{
if(l==r)
{
tree[p]=inf;
return;
}
int mid=(l+r)>>;
build(p<<,l,mid),build(p<<|,mid+,r);
tree[p]=inf;
}
int query(int p,int l,int r,int x)
{
push_down(p,l,r);
if(l==r)return tree[p];
int mid=(l+r)>>;
if(x<=mid) return query(p<<,l,mid,x);
else return query(p<<|,mid+,r,x);
}
}A,B;
struct sam
{
int last,cnt,rt;
int fa[N],mx[N],c[N][];
sam(){last=cnt=rt=;}
void extend(int x)
{
int p=last,np=last=++cnt;mx[np]=mx[p]+;
while(p&&!c[p][x])
{
c[p][x]=np;
p=fa[p];
}
if(!p)fa[np]=rt;
else
{
int q=c[p][x];
if(mx[q]==mx[p]+)fa[np]=q;
else
{
int nq=++cnt;mx[nq]=mx[p]+;
memcpy(c[nq],c[q],sizeof(c[q]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while(c[p][x]==q)c[p][x]=nq,p=fa[p];
}
}
}
bool flag[N];
void build()
{
memset(flag,true,sizeof(flag));
for (int i=;i<=cnt;i++)
flag[fa[i]]=false;
for (int i=;i<=cnt;i++)
if(flag[i])
{
int l=mx[i]-mx[fa[i]],r=mx[i];
A.update(,,n,,l-,r+);
B.update(,,n,l,r,r-l+);
}
}
}sam;
void solve()
{
for (int i=;i<=n;i++)
printf("%d\n",min(A.query(,,n,i)-i,B.query(,,n,i)));
}
int main()
{
freopen("fzy.in","r",stdin);
freopen("fzy.out","w",stdout);
scanf("%s",ch+);n=strlen(ch+);
for (int i=;i<=n;i++)
sam.extend(ch[i]-'a');
A.build(,,n),B.build(,,n);
// cout<<1<<endl<<endl;
sam.build(),solve();
}
bzoj1396&&2865 识别子串 后缀自动机+线段树的更多相关文章
- BZOJ 1396&&2865 识别子串[后缀自动机 线段树]
Description 在这个问题中,给定一个字符串S,与一个整数K,定义S的子串T=S(i, j)是关于第K位的识别子串,满足以下两个条件: 1.i≤K≤j. 2.子串T只在S中出现过一次. 例如, ...
- 【BZOJ1396】识别子串 - 后缀自动机+线段树
题意: Description Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. 题解: ...
- bzoj 1396/2865: 识别子串 后缀自动机+线段树
水水的字符串题 ~ #include <map> #include <cstdio> #include <cstring> #include <algorit ...
- BZOJ1396: 识别子串(后缀自动机 线段树)
题意 题目链接 Sol 后缀自动机+线段树 还是考虑通过每个前缀的后缀更新答案,首先出现次数只有一次,说明只有\(right\)集合大小为\(1\)的状态能对答案产生影响 设其结束位置为\(t\),代 ...
- BZOJ 1396 识别子串 (后缀自动机+线段树)
题目大意: 给你一个字符串S,求关于每个位置x的识别串T的最短长度,T必须满足覆盖x,且T在S中仅出现一次 神题 以节点x为结尾的识别串,必须满足它在$parent$树的子树中只有一个$endpos$ ...
- BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
这道题各位大神好像都是用后缀自动机做的?.....蒟蒻就秀秀智商写一写后缀数组解法..... 求出Height数组后, 我们枚举每一位当做子串的开头. 如上图(x, y是height值), Heigh ...
- 2018.12.23 bzoj2865&&1396: 字符串识别(后缀自动机+线段树)
传送门 卡空间差评! 题意简述:给一个字串,对于每个位置求出经过这个位置且只在字串中出现一次的子串的长度的最小值. 解法:先建出samsamsam,显然只有当sizep=1size_p=1sizep ...
- bzoj千题计划319:bzoj2865: 字符串识别(后缀自动机 + 线段树)
https://www.lydsy.com/JudgeOnline/problem.php?id=2865 同上一篇博客 就是卡卡空间,数组改成map #include<map> #inc ...
- cf666E. Forensic Examination(广义后缀自动机 线段树合并)
题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并 首先对所有的\(t_i\)建个广义后缀自动机,这样可以得到所有子串信息. 考虑把询问离线,然后把\(S\)拿到自动机上跑,同时维护一下 ...
随机推荐
- pip更改国内源
国内源: 阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/豆瓣(dou ...
- scrapy--boss直聘
Hi,大家好.有段时间没来更新scrapy爬取实例信息了,前2天同事说爬取拉勾,boss直聘等网站信息比较困难.昨天下午开始着手爬取boss直聘内Python爬虫的信息,比想象中的简单很多. 需要解决 ...
- tcl之控制流-foreach
- 一行代码搞定checkbox全选和全不选
<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...
- Android 第三方库RxLifecycle使用
1.简单介绍RxLifecycle 1.1.使用原因. 在使用rxjava的时候,如果没有及时解除订阅,在退出activity的时候,异步线程还在执行. 对activity还存在引用,此时就会产生内存 ...
- Android 数据库中的数据给到ListView
前言:因为之前学的都是用一个自己定义的类,完成将某一个bean中的数据直接获取,而实际中通常是通过数据库来得到的,总之,最终就是要得到数据.提一下最重要的东西,我把它叫做代理,如同一个校园代理,没有他 ...
- spring boot 入门1-----如何使用@Value注解读取配置文件以及使用@ConfigrationProperties注解
读取.yml文件属性值的方式 1)如何将配置文件中的属性值与字段匹配起来 @Value("${配置文件中属性的名}") 在application.yml文件中 server: po ...
- 无限小数转分数POJ1930分析
将无限小数化为分数,有一套简单的公式.使其轻松表示出来. 循环节 例如:0.121212…… 循循环节为12. 公式 这个公式必须将循环节的开头放在十分位.若不是可将原数乘10^x(x为正整数) ...
- runtime怎么添加属性、方法等
ivar表示成员变量 class_addIvar class_addMethod class_addProperty class_addProtocol class_replaceProperty
- 风格指南--C++
0.避免多重包含是学编程时基本的要求; 1. 前置声明是为了降低编译依赖,防止修改一个头文件引发多米诺效应; 2. 内联函数的合理使用可提高代码执行效率; 3. ‐inl.h 可提高代码可读性 (一般 ...