BZOJ1396 识别子串 和 BZOJ2865 字符串识别
字符串识别
2865: 字符串识别
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 839 Solved: 261
[Submit][Status][Discuss]
Description
XX在进行字符串研究的时候,遇到了一个十分棘手的问题。
在这个问题中,给定一个字符串S,与一个整数K,定义S的子串T=S(i, j)是关于第K位的识别子串,满足以下两个条件:
1、i≤K≤j。
2、子串T只在S中出现过一次。
例如,S="banana",K=5,则关于第K位的识别子串有"nana","anan","anana","nan","banan"和"banana"。
现在,给定S,XX希望知道对于S的每一位,最短的识别子串长度是多少,请你来帮助他。
Input
仅一行,输入长度为N的字符串S。
Output
输出N行,每行一个整数,第i行的整数表示对于第i位的最短识别子串长度。
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
HINT
N<=5*10^5
Source
[Submit][Status][Discuss]
HOME
Back
jklover的题解
SAM + 线段树.
先建出 parent 树,按照题意,我们只需要处理 right 集合大小为 1 的节点.
如下图,先算出这样的一个节点合法长度的 max,min ( min 可以用 max(fa)+1 计算).
那么区域 I 内每个点的贡献就是区域 II 的长度加上这个点到区域 II 的距离.
区域 II 内每个点的贡献就是区间 II 的长度.开两颗线段树分别修改就可以了.
如何维护区域1呢?考虑他的答案是pos[u]-i+1,直接更新pos[u],那么把最终线段树上的值-i就是答案了。这种操作比较常见。
时间复杂度\(O(n \log n)\)
co int N=2e5,INF=0x3f3f3f3f;
struct node{int min,tag;};
#define lc (x<<1)
#define rc (x<<1|1)
struct SegTree{
node t[N*4];
void pushup(int x){
t[x].min=min(t[lc].min,t[rc].min);
}
void modify(int x,int v){
t[x].min=min(t[x].min,v),t[x].tag=min(t[x].tag,v);
}
void pushdown(int x){
if(t[x].tag<INF){
modify(lc,t[x].tag),modify(rc,t[x].tag);
t[x].tag=INF;
}
}
void build(int x,int l,int r){
t[x].min=t[x].tag=INF;
if(l==r) return;
int mid=l+r>>1;
build(lc,l,mid),build(rc,mid+1,r);
}
void update(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr) return modify(x,v);
pushdown(x);
int mid=l+r>>1;
if(ql<=mid) update(lc,l,mid,ql,qr,v);
if(qr>mid) update(rc,mid+1,r,ql,qr,v);
pushup(x);
}
}T1,T2;
int ans[N];
void query(int x,int l,int r){
if(l==r) return ans[l]=min(T1.t[x].min-l,T2.t[x].min),void();
T1.pushdown(x),T2.pushdown(x);
int mid=l+r>>1;
query(lc,l,mid),query(rc,mid+1,r);
}
// SAM
char buf[N];
int n,tot=1,last=1;
int ch[N][26],fa[N],len[N],pos[N],siz[N];
void extend(int c,int po){
int p=last,cur=last=++tot;
len[cur]=len[p]+1,pos[cur]=po,siz[cur]=1;
for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=cur;
if(!p) fa[cur]=1;
else{
int q=ch[p][c];
if(len[q]==len[p]+1) fa[cur]=q;
else{
int clone=++tot;
memcpy(ch[clone],ch[q],sizeof ch[q]);
fa[clone]=fa[q],len[clone]=len[p]+1,pos[clone]=pos[q];
fa[q]=fa[cur]=clone;
for(;ch[p][c]==q;p=fa[p]) ch[p][c]=clone;
}
}
}
int cnt[N],ord[N];
int main(){
scanf("%s",buf+1),n=strlen(buf+1);
for(int i=1;i<=n;++i) extend(buf[i]-'a',i);
for(int i=1;i<=tot;++i) ++cnt[len[i]];
for(int i=1;i<=n;++i) cnt[i]+=cnt[i-1];
for(int i=1;i<=tot;++i) ord[cnt[len[i]]--]=i;
T1.build(1,1,n),T2.build(1,1,n);
for(int i=tot;i>=1;--i){
int u=ord[i];
siz[fa[u]]+=siz[u];
if(u==1||siz[u]>1) continue;
int l=pos[u]-len[u]+1,r=pos[u]-len[fa[u]];
if(l<=r-1) T1.update(1,1,n,l,r-1,pos[u]+1);
T2.update(1,1,n,r,pos[u],len[fa[u]]+1);
}
query(1,1,n);
for(int i=1;i<=n;++i) printf("%d\n",ans[i]);
return 0;
}
BZOJ1396 识别子串 和 BZOJ2865 字符串识别的更多相关文章
- bzoj 1396: 识别子串 && bzoj 2865: 字符串识别【后缀数组+线段树】
根据height数组的定义,和当前后缀串i最长的相同串的长度就是max(height[i],height[i+1]),这个后缀贡献的最短不同串长度就是len=max(height[i],height[ ...
- 【BZOJ1396】识别子串&【BZOJ2865】字符串识别(后缀自动机)
[BZOJ1396]识别子串&[BZOJ2865]字符串识别(后缀自动机) 题面 自从有了DBZOJ 终于有地方交权限题了 题解 很明显,只出现了一次的串 在\(SAM\)的\(right/e ...
- bzoj2865 字符串识别
Description XX在进行字符串研究的时候,遇到了一个十分棘手的问题. 在这个问题中,给定一个字符串S,与一个整数K,定义S的子串T=S(i, j)是关于第K位的识别子串,满足以下两个条件: ...
- bzoj千题计划319:bzoj2865: 字符串识别(后缀自动机 + 线段树)
https://www.lydsy.com/JudgeOnline/problem.php?id=2865 同上一篇博客 就是卡卡空间,数组改成map #include<map> #inc ...
- 【bzoj1396】 识别子串
http://www.lydsy.com/JudgeOnline/problem.php?id=1396 (题目链接) 题意 问字符串S每一位的最短识别子串是多长(识别子串指包含这个字符且只出现在S中 ...
- 【BZOJ-1396&2865】识别子串&字符串识别 后缀自动机/后缀树组 + 线段树
1396: 识别子串 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 312 Solved: 193[Submit][Status][Discuss] ...
- [BZOJ1396&2865]识别子串
bzoj1396 bzoj2865 dbzoj1396 dbzoj2865 题面 XX在进行字符串研究的时候,遇到了一个十分棘手的问题. 在这个问题中,给定一个字符串\(S\),与一个整数\(K\), ...
- BZOJ1396:识别子串(SAM)
Description Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. Sample I ...
- bzoj1396&&2865 识别子串 后缀自动机+线段树
Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. Sample Input agoodco ...
随机推荐
- Qt去掉treeview项的焦点虚线
项目做到后期,进行局部美化的时候发现了问题,在treeview框选择状态下会有虚线. 其实,不仅是treeview,tableview,listview,乃至button在有焦点的情况下,都会出现虚线 ...
- 【转帖】处理器史话 | 这张漫画告诉你,为什么双核CPU能打败四核CPU?
处理器史话 | 这张漫画告诉你,为什么双核CPU能打败四核CPU? https://www.eefocus.com/mcu-dsp/371324 2016-10-28 10:28 作者:付丽华预计 9 ...
- Java开发笔记(一百二十八)Swing的图标
前面提过,AWT没提供能够直接显示图像的控件,这无疑是个令人诟病的短板,因为一上来就得由程序员自己去定义新控件,对于初学者来讲很不友好.这个问题在Swing中也解决掉了,不过Swing并未提供单独的图 ...
- Linux03 文件的相关操作(touch、rm、mv、cat)
一.touch:创建文件 进入相关的目录,使用touch 文件名 keshengtao@LAPTOP-F9AFU4OK:~$ touch kst.py keshengtao@LAPTOP-F9AFU4 ...
- 「CTS2019」珍珠
「CTS2019」珍珠 解题思路 看了好多博客才会,问题即要求有多少种方案满足数量为奇数的变量数 \(\leq n-2m\).考虑容斥,令 \(F(k)\) 为恰好有 \(n\) 个变量数量为奇数的方 ...
- 使用lxml解析HTML代码
做个参考,转自:https://blog.csdn.net/qq_42281053/article/details/80658018
- C#的WebApi 与 EasyUi的DataGrid结合生成的可分页界面
1.从数据库每次取出的数据为当前分页的数据. 2.分页用的是EasyUI 的 Pagination控件,与DataGrid是相对独立的. 3.后台数据获取是通过WebApi去获取. 4.传入参数是:p ...
- .net语音播放,自定义播报文字
// using System.Speech.Synthesis; SpeechSynthesizer synth = new SpeechSynthesizer(); // Configure th ...
- Linux环境Ubuntu上安装GitLab
本文主要介绍在Ubuntu[Ubuntu 18.04.3]上安装最新的GitLab版本控制工具. 一.安装更新GitLab所需要的依赖项 sudo apt-get update 下载过程中,网络要有所 ...
- 1 集群状态、增删改查、全量替换、强制创建、设置单个index的分片数副本数
检查集群健康状态,可以看集群颜色.(黄色:primary shard都正常,replica不正常) GET /_cat/health?v 列出集群所有index GET /_cat/indices?v ...