【LOJ#6041】事情的相似度(后缀自动机)

题面

LOJ

题解

\(\mbox{YCB}\)搬了这道题目。。。\(\mbox{QwQ}\)

还是用到\(lcp\)就是\(parent\)树上的\(LCA\)的\(len\)。

每次询问显然就是区间内点的贡献。

那么考虑所有可能出现的点对。

显然对于两个子串而言,只会匹配最靠近的两个。

那么用\(set\)维护\(endpos\)集合,每次合并的时候将两个最靠近的位置合并成为一个点对,其贡献就是当前点的\(len\)。

那么最终询问扫描线解决即可。

\(zsy\)还有一种用\(LCT\)的做法,大致口胡一下就是类似上面的操作,要求的就是一个链并。每次将当前点到根节点的路径染色,那么每次的交点就是一个\(LCA\)。发现染色操作类似\(LCT\)的\(access\),因此直接这么模拟即可。

代码是第一种做法的。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;
#define ll long long
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,m;
char ch[MAX];
struct Node{int son[26],len,ff;}t[MAX<<1];
int last,tot,sum;
set<int> S[MAX<<1];
void extend(int id,int c)
{
int p=last,np=++tot;last=np;
t[np].len=t[p].len+1;
while(p&&!t[p].son[c])t[p].son[c]=np,p=t[p].ff;
if(!p)t[np].ff=1;
else
{
int q=t[p].son[c];
if(t[q].len==t[p].len+1)t[np].ff=q;
else
{
int nq=++tot;
t[nq]=t[q];t[nq].len=t[p].len+1;
t[np].ff=t[q].ff=nq;
while(p&&t[p].son[c]==q)t[p].son[c]=nq,p=t[p].ff;
}
}
S[np].insert(id);
}
struct Point{int u,v,len;}p[MAX<<5];
bool operator<(Point a,Point b){return (a.v!=b.v)?a.v<b.v:((a.u!=b.u)?a.u<b.u:a.len<b.len);}
struct Line{int v,next;}e[MAX<<2];
int h[MAX<<1],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
void dfs(int u)
{
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;dfs(v);if(!t[u].len)continue;
if(S[u].size()<S[v].size())swap(S[u],S[v]);
set<int>::iterator it,nw,pre,nxt;
for(it=S[v].begin();it!=S[v].end();++it)
{
S[u].insert(*it);nw=pre=nxt=S[u].find(*it);++nxt;
if(pre!=S[u].begin())--pre,p[++sum]=(Point){*pre,*nw,t[u].len};
if(nxt!=S[u].end())p[++sum]=(Point){*nw,*nxt,t[u].len};
S[u].erase(*it);
}
for(it=S[v].begin();it!=S[v].end();++it)S[u].insert(*it);
}
}
struct Qry{int l,r,id;}q[MAX];
bool operator<(Qry a,Qry b){return (a.r!=b.r)?a.r<b.r:a.l<b.l;}
int ans[MAX];
int c[MAX];
int lb(int x){return x&(-x);}
void add(int x,int w){while(x)c[x]=max(c[x],w),x-=lb(x);}
int Query(int x){int ret=0;while(x<=n)ret=max(ret,c[x]),x+=lb(x);return ret;}
int main()
{
n=read();m=read();last=tot=1;scanf("%s",ch+1);
for(int i=1;i<=n;++i)extend(i,ch[i]-48);
for(int i=2;i<=tot;++i)Add(t[i].ff,i);
dfs(1);sort(&p[1],&p[sum+1]);
for(int i=1;i<=m;++i)q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(&q[1],&q[m+1]);
for(int i=1,j=1;i<=m;++i)
{
while(j<=sum&&p[j].v<=q[i].r)add(p[j].u,p[j].len),++j;
ans[q[i].id]=Query(q[i].l);
}
for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
return 0;
}

【LOJ#6041】事情的相似度(后缀自动机)的更多相关文章

  1. LOJ #6041. 事情的相似度

    Description 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的 ...

  2. 【loj6041】「雅礼集训 2017 Day7」事情的相似度 后缀自动机+STL-set+启发式合并+离线+扫描线+树状数组

    题目描述 给你一个长度为 $n$ 的01串,$m$ 次询问,每次询问给出 $l$ .$r$ ,求从 $[l,r]$ 中选出两个不同的前缀的最长公共后缀长度的最大值. $n,m\le 10^5$ 题解 ...

  3. 洛谷 P4248 / loj 2377 [AHOI2013] 差异 题解【后缀自动机】【树形DP】

    可能是一个 SAM 常用技巧?感觉 SAM 的基础题好多啊.. 题目描述 给定一个长度为 \(n\) 的字符串 \(S\) ,令 \(T_i\) 表示它从第 \(i\) 个字符开始的后缀,求: \[ ...

  4. 洛谷 P3975 / loj 2102 [TJOI2015] 弦论 题解【后缀自动机】【拓扑排序】

    后缀自动机入门. 题目描述 为了提高智商,ZJY 开始学习弦论. 这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为 \(n\) 的字符串,求出它的第 \ ...

  5. LOJ6041. 「雅礼集训 2017 Day7」事情的相似度 [后缀树,LCT]

    LOJ 思路 建出反串的后缀树,发现询问就是问一个区间的点的\(lca\)的深度最大值. 一种做法是dfs的时候从下往上合并\(endpos\)集合,发现插入一个点的时候只需要把与前驱后继的贡献算进去 ...

  6. 【LOJ 6041】「雅礼集训 2017 Day7」事情的相似度

    Description 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的 ...

  7. 【刷题】LOJ 6041 「雅礼集训 2017 Day7」事情的相似度

    题目描述 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的有相同的事情发 ...

  8. [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)

    题目描述 给一个小写字母字符串 S ,q 次询问每次给出 l,r ,求 s[l..r] 的 Border . Border: 对于给定的串 s ,最大的 i 使得 s[1..i] = s[|s|-i+ ...

  9. 「雅礼集训 2017 Day7」事情的相似度

    「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...

随机推荐

  1. 同一个解决方案或有依赖关系的两个项目引用同名但不同版本的DLL

    问题描述 我们最近在使用Redis作Session的集中化,中间碰到了一个如下问题:我们有一些项目比较老,引用了NewtonJson的4.0.3.0版本的DLL,但是Redis提供的C#集成DLL引用 ...

  2. Nginx URL后面不加斜杠301重定向

    今天开发碰到一个问题,其实之前就有这个问题,但是一直都没去关注,今天测试碰到了就解决一下. 问题情况: 当我请求 http://admindev.jingruiauto.com/store/views ...

  3. Luogu P2602 [ZJOI2010]数字计数

    这算是一道数位DP的入门题了吧虽然对于我来说还是有点烦 经典起手式不讲了吧,\(ans(a,b)\to ans(1,b)-ans(1,a-1)\) 我们首先预处理一个东西,用\(f_i\)表示有\(i ...

  4. R实战 第十篇:列联表和频数表

    列联表是观测数据按两个或更多属性(定性变量)分类时所列出的频数分布表,它是由两个以上的变量进行交叉分类的频数分布表.交互分类的目的是将两变量分组,然后比较各组的分布状况,以寻找变量间的关系. 按两个变 ...

  5. Android 安全退出应用程序的方法总结

    正常关闭应用程序: 当应用不再使用时,通常需要关闭应用,可以使用以下三种方法关闭android应用: 第一种方法:首先获取当前进程的id,然后杀死该进程. android.os.Process.kil ...

  6. Webpack 2 视频教程 003 - Webpack 项目初始化

    原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...

  7. Python零基础入门(安装步骤,验证方式, 简单操作)

    本篇文章适合新人小白初步了解Python,涵盖Python的介绍.安装以及简单的基础操作.  1.Python简介 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.它的设 ...

  8. zabbix邮件报警功能的验证

    zabbix里面设置了很多监控项,有很多重要的监控预警,必须保证zabbix邮件报警功能正常,以确保那些告警信息能及时发送到运维人员的邮箱里. 所以需要每天8:30发一封确认zabbix邮件报警功能正 ...

  9. linux-阿里云仓库搭建-搭建本地仓库-yum

    以上是同步元数据信息 安装完成———————————————————————————— 本地库的搭建 是建立在rpm之上的封装 可用的包 把仓库信息链接到本地 使用中文显示, 我们平时用的是oracl ...

  10. SqlDataAdapter简单介绍 (转)

    From:  http://blog.sobnb.com/u/92/5532.html 一.特点介绍 1.表示用于填充 DataSet 和更新 SQL Server 数据库的一组数据命令和一个数据库连 ...