【BZOJ1396】识别子串(后缀自动机,线段树)
题意:

一行,一个由小写字母组成的字符串S,长度不超过10^5
思路:论文题

设p为自动机上的合法结点,r为右端点,len=st[fa[p]]]+1
位置[r-st[p]+1,r-len+1]与r-i+1取min,其中i为下标
位置[r-len+1,r]与len取min
建立两棵线段树,分别维护r+1和len
因为只有区间修改和单点查询可以不写lazytag
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef pair<ll,int>P;
#define N 100010
#define M 210000
#define fi first
#define se second
#define MP make_pair
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1 const int MOD=1e9+,inv2=(MOD+)/;
double eps=1e-;
int INF=1e9;
ll inf=5e13;
int dx[]={-,,,};
int dy[]={,,-,}; char s[N];
int p,np,q,nq,k,cas,n;
int t[N<<][]; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} void build(int l,int r,int p,int op)
{
t[p][op]=INF;
if(l==r) return;
int mid=(l+r)>>;
build(l,mid,ls,op);
build(mid+,r,rs,op);
} void update(int l,int r,int x,int y,int v,int p,int op)
{
if(x<=l&&r<=y)
{
t[p][op]=min(t[p][op],v);
return;
}
int mid=(l+r)>>;
if(x<=mid) update(l,mid,x,y,v,ls,op);
if(y>mid) update(mid+,r,x,y,v,rs,op);
} int query(int l,int r,int x,int p,int op)
{
if(l==r) return t[p][op];
int mid=(l+r)>>;
if(x<=mid) return min(t[p][op],query(l,mid,x,ls,op));
else return min(t[p][op],query(mid+,r,x,rs,op));
} struct sam
{
int cnt;
int fa[N<<],ch[N<<][];
int st[N<<],b[N<<],bl[N<<],to[N<<],size[N<<]; sam()
{
cnt=np=;
} void add(int x,int i)
{
p=np; st[np=++cnt]=st[p]+;
to[np]=i;
while(p&&!ch[p][x])
{
ch[p][x]=np;
p=fa[p];
}
if(!p) fa[np]=;
else if(st[p]+==st[q=ch[p][x]]) fa[np]=q;
else
{
st[nq=++cnt]=st[p]+;
memcpy(ch[nq],ch[q],sizeof ch[q]);
//t[nq]=t[q];
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while(p&&ch[p][x]==q)
{
ch[p][x]=nq;
p=fa[p];
}
}
} void solve()
{
rep(i,,cnt) b[st[i]]++;
rep(i,,cnt) b[i]+=b[i-];
rep(i,,cnt) bl[b[st[i]]--]=i;
int u=;
rep(i,,n)
{
u=ch[u][s[i]-'a'];
size[u]++;
}
build(,n,,);
build(,n,,);
per(i,cnt,) size[fa[bl[i]]]+=size[bl[i]]; rep(i,,cnt)
{
int p=bl[i];
if(size[p]>) continue;
int len=st[fa[p]]+,r=to[p];
update(,n,r-len+,r,len,,);
update(,n,r-st[p]+,r-len+,r+,,);
} rep(i,,n)
{
int t1=query(,n,i,,),t2=-i+query(,n,i,,);
printf("%d\n",min(t1,t2));
} }
}sam; int main()
{
scanf("%s",s+);
n=strlen(s+);
rep(i,,n) sam.add(s[i]-'a',i);
sam.solve();
return ;
}
【BZOJ1396】识别子串(后缀自动机,线段树)的更多相关文章
- BZOJ1396: 识别子串(后缀自动机 线段树)
题意 题目链接 Sol 后缀自动机+线段树 还是考虑通过每个前缀的后缀更新答案,首先出现次数只有一次,说明只有\(right\)集合大小为\(1\)的状态能对答案产生影响 设其结束位置为\(t\),代 ...
- 【BZOJ1396】识别子串 - 后缀自动机+线段树
题意: Description Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. 题解: ...
- bzoj1396&&2865 识别子串 后缀自动机+线段树
Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. Sample Input agoodco ...
- BZOJ 1396&&2865 识别子串[后缀自动机 线段树]
Description 在这个问题中,给定一个字符串S,与一个整数K,定义S的子串T=S(i, j)是关于第K位的识别子串,满足以下两个条件: 1.i≤K≤j. 2.子串T只在S中出现过一次. 例如, ...
- BZOJ 1396 识别子串 (后缀自动机+线段树)
题目大意: 给你一个字符串S,求关于每个位置x的识别串T的最短长度,T必须满足覆盖x,且T在S中仅出现一次 神题 以节点x为结尾的识别串,必须满足它在$parent$树的子树中只有一个$endpos$ ...
- bzoj 1396/2865: 识别子串 后缀自动机+线段树
水水的字符串题 ~ #include <map> #include <cstdio> #include <cstring> #include <algorit ...
- BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
这道题各位大神好像都是用后缀自动机做的?.....蒟蒻就秀秀智商写一写后缀数组解法..... 求出Height数组后, 我们枚举每一位当做子串的开头. 如上图(x, y是height值), Heigh ...
- BZOJ1396 识别子串 字符串 SAM 线段树
原文链接http://www.cnblogs.com/zhouzhendong/p/9004467.html 题目传送门 - BZOJ1396 题意 给定一个字符串$s$,$|s|\leq 10^5$ ...
- 2018.12.23 bzoj2865&&1396: 字符串识别(后缀自动机+线段树)
传送门 卡空间差评! 题意简述:给一个字串,对于每个位置求出经过这个位置且只在字串中出现一次的子串的长度的最小值. 解法:先建出samsamsam,显然只有当sizep=1size_p=1sizep ...
- bzoj1396识别子串(SAM+线段树)
复习SAM板子啦!考前刷水有益身心健康当然这不是板子题/水题…… 很容易发现只在i位置出现的串一定是个前缀串.那么对答案的贡献分成两部分:一部分是len[x]-fa~len[x]的这部分贡献会是r-l ...
随机推荐
- leetcode 88. C++ 合并两个有序数组
Leetcode 88. 合并两个有序数组 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明: 初始化 nums1 和 ...
- 【OpenCV】 在CentOS下搭建OpenCV开发环境
最近开始入模式识别的坑,自然被迫上OpenCV了. 在多次尝试给VS2015扩展Windows 10 SDK无果后(不要问我为啥..VS2015开发C++的标准库全给扔到这个SDK里了,打包在VS安装 ...
- 【ABAP系列】SAP ABAP模块-任意report作为附件以邮件形式发送
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP模块-任意rep ...
- python while 循环打印九九乘法表
方向一 i = 1 while i <= 9: j = 1 while j <= i print('%d*%d = %2d'%( j,i ,i*j),end='') j += 1 prin ...
- MySQL-第六篇DML语句
1.DML主要操作数据表里的数据,主要完成3个任务: 1>insert:插入数据.格式:insert into ... 2>delete:删除数据.格式:delete from ... 3 ...
- BZOJ 4821 (luogu 3707)(全网最简洁的代码实现之一)
题面 传送门 分析 计算的部分其他博客已经写的很清楚了,本博客主要提供一个简洁的实现方法 尤其是pushdown函数写得很简洁 代码 #include<iostream> #include ...
- Pandas处理缺失的数据
处理丢失数据 有两种丢失数据: None np.nan(NaN) import numpy as np import pandas from pandas import DataFrame 1. No ...
- P3191 [HNOI2007]紧急疏散EVACUATE(费用流)
P3191 [HNOI2007]紧急疏散EVACUATE 费用流+卡常优化 我们只关心一个人通过门时的时间,在空地的行走时间可以分层维护 于是根据时间分层,到门的时候再计算代价,即代价$=$层数 每经 ...
- cronsun任务管理器部署文档
一.cronsun介绍 1)cronsun产生的背景 大量的 crontab 任务散布在各台服务器,带来了很高的维护成本 任务没有按时执行,甚至失败了很久才发现,需要重试或排查 crontab 分散在 ...
- JS中对象数据类型的基本结构和操作
Object类型 ECMAScript中的队形其实就是一组数据和功能的集合.对象可以通过执行new操作符后跟要创建的对象类型的名称来创建.而创建Object类型的示例并为其添加属性和(或)方法,就可以 ...