BZOJ1396:识别子串(SAM)
Description

Input
Output
Sample Input
Sample Output
1
2
3
3
2
2
3
3
2
2
3
3
2
1
2
3
3
2
1
2
3
4
Solution
1A挺开心的省得调了
对于SAM上的每一个节点,我们只需要考虑right集合大小为1的
设一个right集合大小为1的点结束点在endpos,有效长度为[l,r]
那么对于区间[endpos-r+1,endpos-l+1],这个点的贡献为endpos-i+1,用一颗线段树维护endpos+1,i最后计算贡献
对于区间[endpos-l+1,endpos],这个点的贡献为l,再开一颗线段树维护l
最后扫一遍单点查询最小值就好了
标记永久化好像非常短还好写= =
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#define N (200000+1000)
using namespace std; char s[N];
int Ans,n; struct SGT
{
int Segt[N<<];
SGT(){memset(Segt,0x7f,sizeof(Segt));} void Update(int now,int l,int r,int l1,int r1,int k)
{
if (r<l1 || l>r1) return;
if (l1<=l && r<=r1){Segt[now]=min(Segt[now],k);return;}
int mid=(l+r)>>;
Update(now<<,l,mid,l1,r1,k); Update(now<<|,mid+,r,l1,r1,k);
}
void Query(int now,int l,int r,int x)
{
Ans=min(Ans,Segt[now]);
if (l==r) return;
int mid=(l+r)>>;
if (x<=mid) Query(now<<,l,mid,x);
else Query(now<<|,mid+,r,x);
}
}SGT[]; struct SAM
{
int fa[N],son[N][],right[N],step[N],End[N],od[N],wt[N];
int p,q,np,nq,last,cnt;
SAM(){last=++cnt;} void Insert(int x,int pos)
{
p=last; last=np=++cnt; step[np]=step[p]+; right[np]=; End[np]=pos;
while (p && !son[p][x]) son[p][x]=np,p=fa[p];
if (!p) fa[np]=;
else
{
q=son[p][x];
if (step[p]+==step[q]) fa[np]=q;
else
{
nq=++cnt; step[nq]=step[p]+;
memcpy(son[nq],son[q],sizeof(son[q]));
fa[nq]=fa[q]; fa[q]=fa[np]=nq;
while (son[p][x]==q) son[p][x]=nq,p=fa[p];
}
}
}
void Init()
{
int len=strlen(s+);
for (int i=; i<=cnt; ++i) wt[step[i]]++;
for (int i=; i<=len; ++i) wt[i]+=wt[i-];
for (int i=cnt; i>=; --i) od[wt[step[i]]--]=i;
for (int i=cnt; i>=; --i) right[fa[od[i]]]+=right[od[i]];
}
void Solve()
{
for (int i=; i<=cnt; ++i)
if (right[i]==)
{
SGT[].Update(,,n,End[i]-step[i]+,End[i]-step[fa[i]],End[i]+);
SGT[].Update(,,n,End[i]-step[fa[i]],End[i],step[fa[i]]+);
}
for (int i=; i<=n; ++i)
{
Ans=0x7fffffff;
SGT[].Query(,,n,i); Ans-=i;
SGT[].Query(,,n,i);
printf("%d\n",Ans);
}
}
}SAM; int main()
{
scanf("%s",s+);
n=strlen(s+);
for (int i=; i<=n; ++i)
SAM.Insert(s[i]-'a',i);
SAM.Init();
SAM.Solve();
}
BZOJ1396:识别子串(SAM)的更多相关文章
- BZOJ1396 识别子串【SAM+SegmentTree】
BZOJ1396 识别子串 给定一个串\(s\),对于串中的每个位置,输出经过这个位置且只在\(s\)中出现一次的子串的最短长度 朴素的想法是,我们要找到那些只出现一次的子串,之后遍历每个串,把串所覆 ...
- BZOJ-1396: 识别子串
后缀自动机+线段树 先建出\(sam\),统计一遍每个点的\(right\)集合大小\(siz\),对于\(siz=1\)的点\(x\),他所代表的子串只会出现一次,设\(y=fa[x]\),则这个点 ...
- BZOJ1396 识别子串 和 BZOJ2865 字符串识别
字符串识别 2865: 字符串识别 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 839 Solved: 261[Submit][Status][D ...
- 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 ...
- BZOJ1396 识别子串 字符串 SAM 线段树
原文链接http://www.cnblogs.com/zhouzhendong/p/9004467.html 题目传送门 - BZOJ1396 题意 给定一个字符串$s$,$|s|\leq 10^5$ ...
- bzoj1396识别子串(SAM+线段树)
复习SAM板子啦!考前刷水有益身心健康当然这不是板子题/水题…… 很容易发现只在i位置出现的串一定是个前缀串.那么对答案的贡献分成两部分:一部分是len[x]-fa~len[x]的这部分贡献会是r-l ...
- BZOJ bzoj1396 识别子串
题面: bzoj1396 题解: 先建出SAM,并计算right集合大小.显然符合条件的点的right集合大小为1. 对于每个right集合为1的状态显然可以算出这些状态的pos以及maxlen和mi ...
- bzoj1396: 识别子串
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...
随机推荐
- online contest
http://atcoder.jp/contest https://nanti.jisuanke.com/contest http://codeforces.com/ https://www.nowc ...
- plpgsql insert 性能 测试
有时需要执行一些sql脚本,带逻辑控制语句,又不想用高级语言C#.Java之类的,可以直接用plpgsql,类似于Oracle的plsql. do language 'plpgsql' $$ decl ...
- Linux文件上传下载sz 和 rz 命令
windows系统和linux系统之间文件上传和下载用到 rz 和 sz 命令.rz: 上传文件sz:下载文件 先检查是否安装rz,sz模块 安装rz,sz 模块yum search sz安装yum ...
- bash的常用功能呢
一.tab键可以自动补齐命令 二.命令历史 1.history 查看之前敲过的所有命令 2.!历史命令编号 调用历史的某一个命令 三.命令别名 1.设置别名 alias 别名=‘命令’ 2.移除 ...
- express组件学习
一.express 可以做:web application.api... 特性: 适合写简单的路由系统 集成很多模板引擎 中间件系统 二.请求与响应 var express = require('ex ...
- JS学习-基础运动
多物体运动 多个物体用同一个函数时,函数里定义的定时器应该要每个物体对应一个定时器名称,不然会导致未完成运动就被关闭了,因为定时器名称一样,而开启定时器前会清除一下. obj.timer 多值同时运动 ...
- 实现绘制图形的ToolBar
给地图添加绘制图形的ToolBar还是有必要的,比较人性化的功能.图形的样式可以自己定制,也提供了朴实的默认样式.对 dojo 不太懂,出现了许许多多问题,真是蛋疼的一天啊.令人惊喜的是 ArcGis ...
- android 实现类似微信缓存和即时更新好友头像
引言 使用微信时我们会发现,首次进入微信的好友列表时,会加载好友头像,但是再次进入时,就不用重新加载了,而且其他页面都不用重新加载,说明微信的好友头像是缓存在本地的,然后好友修改头像后,又会及时的更新 ...
- Vue2.0的动画效果
本文只是结合一些代码和图片加强对Vue动画的理解,更多资料请戳这里 结合原生CSS实现动画 下面是一张图片,简单清晰明了是吧^-^ 下面是一段代码 <!DOCTYPE html> < ...
- ES6入门——函数的扩展
1.函数参数的默认值 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法.现在ES6可以为函数的参数添加默认值,简洁了许多. ES5 function show(a,b){ b = b ...