bzoj1396识别子串(SAM+线段树)
复习SAM板子啦!考前刷水有益身心健康当然这不是板子题/水题……
很容易发现只在i位置出现的串一定是个前缀串。那么对答案的贡献分成两部分:一部分是len[x]-fa~len[x]的这部分贡献会是r-l+1;剩下一部分1~len-fa-1这部分会和i~r构成答案,写两棵线段树即可。
然后就又是板子题了,两个板子(SAM+线段树)套起来。
#include<bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int N=2e5+,inf=0x3f3f3f3f;
int n,lst=,rt=,cnt=,ch[N][],len[N],fa[N],sz[N];
char s[N];
struct tree{
int mn[N<<];
void init(){memset(mn,0x3f,sizeof mn);}
void pushdown(int rt)
{
if(mn[rt]==inf)return;
mn[rt<<]=min(mn[rt<<],mn[rt]),mn[rt<<|]=min(mn[rt<<|],mn[rt]);
mn[rt]=inf;
}
void update(int L,int R,int v,int l,int r,int rt)
{
if(L<=l&&r<=R){mn[rt]=min(mn[rt],v);return;}
int mid=l+r>>;pushdown(rt);
if(L<=mid)update(L,R,v,lson);
if(R>mid)update(L,R,v,rson);
}
int query(int k,int l,int r,int rt)
{
if(l==r)return mn[rt];
int mid=l+r>>;pushdown(rt);
if(k<=mid)return query(k,lson);
return query(k,rson);
}
}tr1,tr2;
void build(int c)
{
int p=lst,np=++cnt;
len[np]=len[p]+,sz[np]=;
while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
if(!p)fa[np]=rt;
else{
int q=ch[p][c];
if(len[p]+==len[q])fa[np]=q;
else{
int nq=++cnt;
memcpy(ch[nq],ch[q],sizeof ch[q]);
fa[nq]=fa[q],fa[np]=fa[q]=nq,len[nq]=len[p]+;
while(p&&ch[p][c]==q)ch[p][c]=nq,p=fa[p];
}
}
lst=np;
}
int main()
{
scanf("%s",s+),n=strlen(s+);
for(int i=;i<=n;i++)build(s[i]-'a');
for(int i=;i<=cnt;i++)sz[i]=;
for(int i=;i<=cnt;i++)sz[fa[i]]=;
tr1.init(),tr2.init();
for(int i=;i<=cnt;i++)
if(sz[i]==)
{
int l=len[i]-len[fa[i]],r=len[i];
if(l>=)tr1.update(,l-,r+,,n,);
tr2.update(l,r,r-l+,,n,);
}
for(int i=;i<=n;i++)printf("%d\n",min(tr1.query(i,,n,)-i,tr2.query(i,,n,)));
}
bzoj1396识别子串(SAM+线段树)的更多相关文章
- BZOJ1396:识别子串(SAM)
Description Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. Sample I ...
- BZOJ1396 识别子串【SAM+SegmentTree】
BZOJ1396 识别子串 给定一个串\(s\),对于串中的每个位置,输出经过这个位置且只在\(s\)中出现一次的子串的最短长度 朴素的想法是,我们要找到那些只出现一次的子串,之后遍历每个串,把串所覆 ...
- BZOJ1396 识别子串 和 BZOJ2865 字符串识别
字符串识别 2865: 字符串识别 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 839 Solved: 261[Submit][Status][D ...
- BZOJ1396 识别子串 字符串 SAM 线段树
原文链接http://www.cnblogs.com/zhouzhendong/p/9004467.html 题目传送门 - BZOJ1396 题意 给定一个字符串$s$,$|s|\leq 10^5$ ...
- bzoj千题计划318:bzoj1396: 识别子串(后缀自动机 + 线段树)
https://www.lydsy.com/JudgeOnline/problem.php?id=1396 后缀自动机的parent树上,如果不是叶子节点,那么至少有两个子节点 而一个状态所代表子串的 ...
- BZOJ1396: 识别子串(后缀自动机,线段树)
Description Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. Sample I ...
- bzoj 1396: 识别子串【SAM+线段树】
建个SAM,符合要求的串显然是|right|==1的节点多代表的串,设si[i]为right集合大小,p[i]为right最大的r点,这些都可以建出SAM后再parent树上求得 然后对弈si[i]= ...
- BZOJ1396: 识别子串(后缀自动机 线段树)
题意 题目链接 Sol 后缀自动机+线段树 还是考虑通过每个前缀的后缀更新答案,首先出现次数只有一次,说明只有\(right\)集合大小为\(1\)的状态能对答案产生影响 设其结束位置为\(t\),代 ...
- BZOJ-1396: 识别子串
后缀自动机+线段树 先建出\(sam\),统计一遍每个点的\(right\)集合大小\(siz\),对于\(siz=1\)的点\(x\),他所代表的子串只会出现一次,设\(y=fa[x]\),则这个点 ...
随机推荐
- Python 中异常嵌套
在Python中,异常也可以嵌套,当内层代码出现异常时,指定异常类型与实际类型不符时,则向外传,如果与外面的指定类型符合,则异常被处理,直至最外层,运用默认处理方法进行处理,即停止程序,并抛出异常信息 ...
- Python调用c++可执行程序
1.c++编译程序 #include <iostream> using namespace std; int test() { , b = ; return a+b; } int main ...
- 2020/2/2 PHP代码审计之反序列化
0x00 序列化与反序列化 序列化: serialize()把对象转换为字节序列的过程称为对象的序列化 反序列化: unserialize()把字节序列恢复为对象的过程称为对象的反序列化 0x01 序 ...
- promise核心技术 1 实例对象/函数对象
一个程序员要在看到代码的语法同时判断数据类型 知道语法是基础 基础才能延伸功能 //一行代码 a()[0]() // a() 首先推断出a是一个函数 //a()[0] 判断a函数的返回值是一个数组 ...
- redis常用命令--zsets
zsets常用命令: zadd key score1 mb1 [score2 mb2....]:像key中添加元素和这个元素的分数,如果元素已经存在,则替换分数. zscore key mb :获取k ...
- HTML5新标签使用及CSS选择器(伪类)
这些标签能够让搜索引擎更直接的解析页面内容. <header></header>语义:文档或者页面的头部 <nav></nav>语义:导航这两者不是组合 ...
- elasticsearch + springboot 整合
https://blog.csdn.net/chengyuqiang/article/details/102938266 https://blog.csdn.net/chengyuqiang/arti ...
- C/C++源程序到可执行程序的过程
源程序.cpp 预处理得到 预处理文件.i 编译得到 汇编文件.S 汇编得到 目标文件.o 链接得到 可执行文件 例子:main.cpp fun.cpp fun.h #inclu ...
- css块级元素
<CSS权威指南>中文字显示:任何不是块级元素的可见元素都是内联元素.其表现的特性是“行布局”形式,这里的“行布局”的意思就是说其表现形式始终以行进行显示.比如,我们设定一个内联元素bor ...
- vue 插槽 part3
f vue中的插槽 1.<slot>默认内容</slot> 当副组件不传递信息的时候 显示默认内容 2.<slot></slot> 显示的是插槽中所有的 ...