[BZOJ1396&2865]识别子串
bzoj1396
bzoj2865
dbzoj1396
dbzoj2865
题面
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\)的每一位,最短的识别子串长度是多少,请你来帮助他。
sol
子串\(T\)只在\(S\)中出现过一次?那不就是\(|endpos|=1\)?
所以说怎么求\(endpos\)呢?
其实,对于\(|endpos|=1\)的点来说,他的\(len\)就是\(endpos\)。
而且一个\(|endpos|=1\)的点是一定没有子节点的,所以很容易就可以找出所有的这种点。
假设我们已经找出了一个\(|endpos|=1\)的点\(i\),那么以这个点为结束位置的且在原串中只出现一次的子串的长度范围就是\([len_{fa_i}+1,len_i]\)。
考虑他对每个位置的贡献。记\(l=len_i-len_{fa_i},r=len_i\),那么对于区间\([l,r]\),获得的贡献是\(len_{fa_i}+1\),也就是满足长度范围的最小值。
而对于区间\([1,l-1]\),由于要保证\(i\le K \le j\)的限制,所以获得的贡献会是一个等差数列。
最后的答案就是每个位置上的最小值。
等差数列怎么维护?开两棵线段树其中一棵减个下标就好了。
code
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e6+5;
int n,last=1,tot=1,tr[N][26],fa[N],len[N],fg[N];
char s[N];
struct segment_tree{
int t[N<<1];
void init(){memset(t,63,sizeof(t));}
void modify(int x,int l,int r,int ql,int qr,int v)
{
if (ql>qr) return;
if (l>=ql&&r<=qr) {t[x]=min(t[x],v);return;}
int mid=l+r>>1;
if (ql<=mid) modify(x<<1,l,mid,ql,qr,v);
if (qr>mid) modify(x<<1|1,mid+1,r,ql,qr,v);
}
int query(int x,int l,int r,int p)
{
if (l==r) return t[x];
t[x<<1]=min(t[x<<1],t[x]);t[x<<1|1]=min(t[x<<1|1],t[x]);
int mid=l+r>>1;
if (p<=mid) return query(x<<1,l,mid,p);
else return query(x<<1|1,mid+1,r,p);
}
}A,B;
void extend(int c)
{
int v=last,u=++tot;last=u;
len[u]=len[v]+1;
while (v&&!tr[v][c]) tr[v][c]=u,v=fa[v];
if (!v) fa[u]=1;
else{
int x=tr[v][c];
if (len[x]==len[v]+1) fa[u]=x;
else{
int y=++tot;
memcpy(tr[y],tr[x],sizeof(tr[y]));
fa[y]=fa[x];fa[x]=fa[u]=y;len[y]=len[v]+1;
while (v&&tr[v][c]==x) tr[v][c]=y,v=fa[v];
}
}
}
int main()
{
scanf("%s",s+1);n=strlen(s+1);
for (int i=1;i<=n;++i) extend(s[i]-'a');
for (int i=1;i<=tot;++i) fg[i]=1;
for (int i=1;i<=tot;++i) fg[fa[i]]=0;
A.init();B.init();
for (int i=1;i<=tot;++i)
if (fg[i])
{
int l=len[i]-len[fa[i]],r=len[i];
A.modify(1,1,n,1,l-1,r+1);
B.modify(1,1,n,l,r,r-l+1);
}
for (int i=1;i<=n;++i)
printf("%d\n",min(A.query(1,1,n,i)-i,B.query(1,1,n,i)));
return 0;
}
[BZOJ1396&2865]识别子串的更多相关文章
- bzoj1396&&2865 识别子串 后缀自动机+线段树
Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. Sample Input agoodco ...
- BZOJ1396&2865 识别子串 【后缀自动机 + 线段树】
题目 输入格式 一行,一个由小写字母组成的字符串S,长度不超过10^5 输出格式 L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. 输入样例 agoodcookcooksg ...
- 【BZOJ1396】识别子串&【BZOJ2865】字符串识别(后缀自动机)
[BZOJ1396]识别子串&[BZOJ2865]字符串识别(后缀自动机) 题面 自从有了DBZOJ 终于有地方交权限题了 题解 很明显,只出现了一次的串 在\(SAM\)的\(right/e ...
- 【bzoj1396】 识别子串
http://www.lydsy.com/JudgeOnline/problem.php?id=1396 (题目链接) 题意 问字符串S每一位的最短识别子串是多长(识别子串指包含这个字符且只出现在S中 ...
- BZOJ 1396&&2865 识别子串[后缀自动机 线段树]
Description 在这个问题中,给定一个字符串S,与一个整数K,定义S的子串T=S(i, j)是关于第K位的识别子串,满足以下两个条件: 1.i≤K≤j. 2.子串T只在S中出现过一次. 例如, ...
- BZOJ 1396||2865 识别子串
这个不是题解,看不懂的,别看了 明明应该是会的,怎么还是写了6个小时呢... 把后缀数组.height数组.排名数组求出来,那么对于原串s的任意子串[x,y](表示第x个到第y个字符组成的子串,字符从 ...
- 【BZOJ1396】识别子串 - 后缀自动机+线段树
题意: Description Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. 题解: ...
- bzoj 1396/2865: 识别子串 后缀自动机+线段树
水水的字符串题 ~ #include <map> #include <cstdio> #include <cstring> #include <algorit ...
- 【BZOJ1396】识别子串(后缀自动机,线段树)
题意: 一行,一个由小写字母组成的字符串S,长度不超过10^5 思路:论文题 设p为自动机上的合法结点,r为右端点,len=st[fa[p]]]+1 位置[r-st[p]+1,r-len+1]与r-i ...
随机推荐
- 【BZOJ4026】dC Loves Number Theory 分解质因数+主席树
[BZOJ4026]dC Loves Number Theory Description dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯竭的水题资源. 给 ...
- 如何基于EasyDSS体系的全套SDK完成各种场景下的视频应用需求
需求背景 回顾EasyDSS的发展过程,基本上保持的是先局部后系统.先组件后平台的发展方式,一步一步夯实每一个细节功能点,从最基础.最兼容的音视频数据的拉流获取,到高效的.全兼容的数据推流,再到流媒体 ...
- hibernate 多对多操作(级联操作)
一.级联保存 分别在用户和角色配置文件中在set标签中加入cascade="save-update": 示例:添加同时添加用户对象和角色对象并关联两个对象: 只需将角色放入用户对象 ...
- 18.Django原生SQL语句查询返回字典
在django中执行自定义语句的时候,返回的结果是一个tuple ,并我不是我所期望的dict.当结果是tuple 时,如果要取得数据,必须知道对应数据在结果集中的序号,用序号的方式去得到值. 如果是 ...
- SAP号码段
[转http://blog.csdn.net/wengyupeng/article/details/8513527] 1.通用Tcode:SNRO 常用维护特定Number range Tcode: ...
- python 发送邮件的两种方式【终极篇】
一,利用python自带的库 smtplib简单高效 from email.mime.multipart import MIMEMultipart from email.mime.text impor ...
- LeetCode:范围求和||【598】
LeetCode:范围求和||[598] 题目描述 给定一个初始元素全部为 0,大小为 m*n 的矩阵 M 以及在 M 上的一系列更新操作. 操作用二维数组表示,其中的每个操作用一个含有两个正整数 a ...
- LeetCode:位运算实现加法
LeetCode:位运算实现加法 写在前面 位运算符 实现加法的思路 两个加数,比如5(101)和6(110),如何不用加法就能得出两者之和呢? 我们知道二进制计算中,如果使用异或将会产生无进位的两者 ...
- Python OOP(1)
类(Class): 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例. 类变量:类变量在整个实例化的对象中是公用的.类变量定义在类中且在函数体之外. ...
- [原创]java WEB学习笔记43:jstl 介绍,core库详解:表达式操作,流程控制,迭代操作,url操作
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...