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\)拿到自动机上跑,同时维护一下 ...
随机推荐
- Centos 7 下安装mysql
// 卸载原有maridb-lib库 [root@localhost ~]# rpm -qa | grep mariadb mariadb-libs-5.5.41-2.el7_0.x86_64 [ro ...
- JAVAOOP异常
排序: Try-catch-finally:try正常执行,如果有异常执行catch后执行finally,如果没有直接执行finally 执行顺序:try-catch:try中的语句正常执行,如果遇到 ...
- 【Python 2 到 3 系列】 print 是函数
v3.0 以前,print一直作为语法结构存在,他是python语法的一部分:这个理解起来可能有点蹩脚,但的确是这样. print 一直被定以为一个statement,也就是说,他跟return/tr ...
- 关于移动端video标签层级问题
这是在微信中正常页面,就是用了一个原生video标签没做任何处理.然后顶部是固定页面顶端的,这个时候向上滑动页面时,会出现下图现象 这个时候正常人都会想到z-index问题,我也是这样想的,可惜很抱歉 ...
- protues7.5安装
win8 + protues7.5的安装 首先找到解压的文件夹,然后按照一步一步安装,如果中间出现不一样的,请退到前一步重新安装, 注意,安装的目录不要出现中文路径.
- auto用法
在C++11中,如果编译器在定义一个变量的时候可以推断出变量的类型,不用写变量的类型,你只需写auto即可. 第一种用法:自动推到内置类型 int x = 100; //C++ 11 auto x = ...
- python—— 文件的打开模式和文件对象方法 & os、os.path 模块中关于文件、目录常用的函数使用方法
引用自“鱼c工作室” 文件的打开模式和文件对象方法 : https://fishc.com.cn/forum.php?mod=viewthread&tid=45279&ext ...
- __builtin_popcount() 函数
详解 该函数的主要作用是计算一个数字的二进制中有多少个1,返回值就是其中1的个数. 它使用一张基于表的方法来进行位搜索,因此这个操作的执行效率很高 此处举一题 P1582 倒水 #include &l ...
- issubclasss/type/isinstance/callable/super
issubclass() : 方法用于判断第一个参数是否是第二个参数的子子孙孙类. 语法:issubclass(sub, super) 检查sub类是否是 super 类的派生类 class A: p ...
- 03,Python网络爬虫第一弹《Python网络爬虫相关基础概念》
爬虫介绍 引入 为什么要学习爬虫,学习爬虫能够为我们以后的发展带来那些好处?其实学习爬虫的原因和为我们以后发展带来的好处都是显而易见的,无论是从实际的应用还是从就业上. 我们都知道,当前我们所处的时代 ...