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 ...
随机推荐
- javadoc 抽出代码中的注释
背景: 在已经有的项目里面利用javadoc来抽出代码中每个类,每个方法的注释部分,形成一个文档. 方法1 利用eslipse来实现 之后会在指定的目录下生成html文档 方法2 利用命令来执行 先把 ...
- Appium元素定位难点:tap坐标定位不准确
tap用法 1.tap是模拟手指点击页面上元素语法有两个参数,第一个是positions,是list类型最多五个点,duration是持续时间,单位毫秒 tap(self, positions, du ...
- Linux定时自动备份oracle数据库
1.在服务器创建备份目录,并赋予权限mkdir -p /backup/P_DATA #新建shell脚本存放路径mkdir -p /backup/P_DB_BACK #新建Oracle数据库备份目录 ...
- css3 网页图片轮播的实现
.lunbo{ height: 640px; width: 100%; background-position: -280px; margin-top: 103px; -webkit-animatio ...
- [高清] Excel函数速记手册
------ 郑重声明 --------- 资源来自网络,纯粹共享交流, 如果喜欢,请您务必支持正版!! --------------------------------------------- 下 ...
- 全栈项目|小书架|服务器开发-Koa2 连接MySQL数据库(Navicat+XAMPP)
为什么使用数据库 为什么需要数据库?-知乎 相比与文件系统,数据库具有以下优势: 高效率:查找效率高 高可用:可数据库共享 安全性强:数据不能随意修改 选择哪个数据库 数据库可以分为关系型数据库和非关 ...
- 编译基于obs-studio的阿里巴巴直播工具tblive的过程和常见问题解决
tblive 简介 tblive开源项目对应的产品是千牛主播,是一个独立的PC端主播工具,基于开源软件OBS Studio来修改定制. 项目说明 tblive是一款优秀的基于obs-studio的直播 ...
- python逻辑编程之kanren
https://github.com/logpy/logpy https://pypi.org/project/kanren/ https://www.yiibai.com/ai_with_pytho ...
- C++ Win32 遍历窗口
查找指定窗口 #include <iostream> #include <windows.h> using namespace std; int main() { TCHAR ...
- CentOS 7 - 里面如何以root身份使用图形界面管理文件?
nautilus 是gnome的文件管理器,但是如果不是root账号下,权限受限,我们可以通过以下方式以root权限使用! 启动shll,随后在shell里面输入下面命令: sudo nautilus