Codeforces.666E.Forensic Examination(广义后缀自动机 线段树合并)

题目链接

\(Description\)

给定串\(S\)\(m\)个串\(T_i\)\(Q\)次询问,每次询问\(l,r,p_l,p_r\),求\(S[p_l\sim p_r]\)\(T_l\sim T_r\)中的哪个串出现次数最多,输出最多次数以及它是\(T\)中的第几个。若最多的有多个,输出下标最小的。

\(Solution\)

挺好的题吧

\(T\)个串建SAM,然后要求出SAM每个节点上\(|right|\)最大的是哪个串。
每个节点的\(|right|\)可以在DFS parent树时合并子节点得到。如果用线段树,区间\(|right|\)最大的是哪个串也可以维护出来。
那么可以离线,在每个点处处理该点上的询问,边DFS边合并线段树得到所有答案。(当然可持久化一下在线也行?)

怎么得到\(S[p_l\sim p_r]\)在SAM上的匹配节点呢?
维护一个节点指针\(p\),拿\(S\)在SAM上尽可能匹配,匹配不了就跳\(fa\)。这样能保证当前\(S\)的后缀(\(S[i]\))一定在\(p\)节点出现了。
所以在\(i\)这里处理\(p_r=i\)的询问。只要我们从当前节点\(p\)一直跳\(fa\),就能找到\(S[p_l,p_r]\)所在的节点,其答案就是该节点的\(|right|\)状态。可以用倍增实现。
(就是从\(S[1,p_r]\)所匹配的节点\(p\)往上跳,跳到从上往下第一个\(len_x\geq p_r-p_l+1\)的节点\(x\)\(x\)就是\(S[p_l,p_r]\)所在的节点)

如果出现次数为\(0\)的话也要输出最靠前的(即\(l\))。=-=

唉 6点多写完代码调到现在 心累

//529ms 56700KB
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define Bit 16
const int N=5e5+5,M=5e4+5,S=M<<1;int m,root[S],fa[S][18];
char s[N],tmp[M];
struct Edge
{int Enum,H[N],nxt[N],to[N];inline void AddEdge(int u,int v){to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;}
}Pos,Qy;
struct Edge2
{int Enum,H[S],nxt[S],to[S];inline void AddEdge(int u,int v){to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;}
}Par;
struct Queries{int l,r,pl,pr;
}q[N];
struct Suffix_Automaton
{int tot,las,fa[S],son[S][26],len[S];Suffix_Automaton() {tot=las=1;}void Insert(int c){int np=++tot,p=las; len[las=np]=len[p]+1;for(; p&&!son[p][c]; p=fa[p]) son[p][c]=np;if(!p) fa[np]=1;else{int q=son[p][c];if(len[q]==len[p]+1) fa[np]=q;else{int nq=++tot; len[nq]=len[p]+1;memcpy(son[nq],son[q],sizeof son[q]);fa[nq]=fa[q], fa[q]=fa[np]=nq;for(; son[p][c]==q; p=fa[p]) son[p][c]=nq;}}}
}sam;
struct Node
{int val,id;bool operator <(const Node &x)const{return val<x.val||(val==x.val&&id>x.id);}
}Ans[N];
struct Segment_Tree
{#define S M*17#define lson son[x][0]#define rson son[x][1]int tot,son[S][2];Node node[S];#undef S#define Update(x) node[x]=std::max(node[lson],node[rson]);void Insert(int &x,int l,int r,int pos){x=++tot;if(l==r) return (void)(node[x]=(Node){1,pos});int m=l+r>>1;pos<=m ? Insert(lson,l,m,pos) : Insert(rson,m+1,r,pos);Update(x);//Update }int Merge(int x,int y){if(!x||!y) return x^y;if(!lson&&!rson) return node[x].val+=node[y].val, x;//叶节点,合并right lson=Merge(lson,son[y][0]), rson=Merge(rson,son[y][1]);Update(x); return x;}Node Query(int x,int l,int r,int L,int R){if(!x) return (Node){0,L};if(L<=l && r<=R) return node[x];int m=l+r>>1;if(L<=m)if(m<R) return std::max(Query(lson,l,m,L,R),Query(rson,m+1,r,L,R));else return Query(lson,l,m,L,R);return Query(rson,m+1,r,L,R);}
}T;inline int read()
{int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now;
}
void DFS(int x)
{for(int i=Par.H[x]; i; i=Par.nxt[i])DFS(Par.to[i]), root[x]=T.Merge(root[x],root[Par.to[i]]);for(int i=Pos.H[x],id; i; i=Pos.nxt[i])id=Pos.to[i], Ans[id]=T.Query(root[x],1,m,q[id].l,q[id].r);
}int main()
{scanf("%s",s+1); int n=strlen(s+1);m=read();for(int i=1; i<=m; ++i){scanf("%s",tmp), sam.las=1;for(int j=0,l=strlen(tmp); j<l; ++j)sam.Insert(tmp[j]-'a'), T.Insert(root[sam.las],1,m,i);//不就是每位的|right[las]|=1吗→_→我在纠结什么 //就是las节点的线段树上,i位置的|right|=1,给i位置+1}int Q=read();for(int i=1; i<=Q; ++i)q[i]=(Queries){read(),read(),read(),read()}, Qy.AddEdge(q[i].pr,i);int lim=sam.tot;for(int x=2; x<=lim; ++x) Par.AddEdge(fa[x][0]=sam.fa[x],x);for(int i=1; i<=Bit; ++i)for(int x=2; x<=lim; ++x)fa[x][i]=fa[fa[x][i-1]][i-1];for(int c,now=0,p=1,i=1; i<=n; ++i){if(sam.son[p][c=s[i]-'a']) p=sam.son[p][c], ++now;//!!!靠 这写错调了两个小时 唉 心累 else{for(c=s[i]-'a'; p&&!sam.son[p][c]; p=sam.fa[p]);if(!p) {p=1, now=0; continue;}now=sam.len[p]+1, p=sam.son[p][c];}for(int j=Qy.H[i],len,id; j; j=Qy.nxt[j]){id=Qy.to[j];if(now<(len=q[id].pr-q[id].pl+1)) continue;int x=p;for(int i=Bit; ~i; --i)if(sam.len[fa[x][i]]>=len) x=fa[x][i];Pos.AddEdge(x,id);}}DFS(1);for(int i=1; i<=Q; ++i)if(!Ans[i].val) printf("%d 0\n",q[i].l);else printf("%d %d\n",Ans[i].id,Ans[i].val);return 0;
}

转载于:https://www.cnblogs.com/SovietPower/p/9368392.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353220.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

键盘键值分类描述

F1-F12键&#xff1a;值从112-123。 主键盘上数字0-9键&#xff1a;值从48-57。字母A-Z键&#xff1a;值从65-90。 ESC键&#xff1a;值27。"~"符号键&#xff1a;值192。 "-"减号键&#xff1a;189。""等号键&#xff1a;187。 " \ "…

MATLAB中的排序函数

全英文帮助没看懂。sort函数其实就是个排序函数。 sort(A)若A是向量不管是列还是行向量&#xff0c;默认都是对A进行升序排列。sort(A)是默认的升序&#xff0c;而sort(A,descend)是降序排序。 sort(A)若A是矩阵&#xff0c;默认对A的各列进行升序排列 sort(A,dim) dim1时等效…

Django启动服务器时,报错mysql的2059错误的原因。

当启动django自带的服务器时&#xff0c;报错2059&#xff1a;> _mysql_exceptions.OperationalError: (2059, )> django.db.utils.OperationalError: (2059, )启动方式为如下&#xff1a;> python manage.py runserver 0.0.0.0:8000经过一番查询&#xff0c;调试&…

2020地区mysql表_2020年甘肃省军队文职考试职位表下载:张掖地区招13人

2020年6月15日全军面向社会招考文职人员公告已发布&#xff0c;全国招聘27073人&#xff0c;甘肃省招聘370人&#xff0c;其中张掖地区总共招聘13人。此次考试博士招考岗位报名时间为2020年6月17日至21日&#xff0c;其他招考岗位报名时间为7月1日至10日。考试时间为2020年8月2…

superhot预告片下载_预告片:裸指关节SOA

superhot预告片下载我正在研究这个想法&#xff0c;但我不知道它是否对你们有吸引力。 我想就您是否需要进一步探讨提出您的意见。 这是一笔交易&#xff1a;我遇到了一些团队&#xff0c;这些团队在使用SOA技术时由于其工具的绝对复杂性而陷入泥潭。 我只在Java中看到过这种情…

J2ME开发环境配置(MyEclipse插件+WTK+jdk)

Myeclipse J2ME开发之环境配置的前言随着移动设备的普及和应用&#xff0c;在小型存储设备方面的研发进入了一个全新的时期,比如数字电视&#xff0c;PDA&#xff0c;移动存储通信设备等。而各方面的技术也进入了一个飞速发展的时期。尤其是近几年J2ME技术的发展。   而开发…

多少秒算长镜头_下中国象棋,能算多少步才算高手?

下象棋&#xff0c;你能算多少步&#xff1f;这是一个让初学者很困扰&#xff0c;也很感兴趣的话题。 很多象棋爱好者说&#xff1a;我最多看2步&#xff0c;我觉得能看5步以上的&#xff0c;就是超级高手高手高高手了。 但一代象棋宗师、14届全国冠军胡荣华的看法则颇有“玄学…

[湖南师大集训2018 7 26] hunger 解题报告 (SPFA)

饿 (hungry.pas/c/cpp) 【背景描述】 给出?个面值分别为?? 的纸币&#xff0c;每种纸币有无限张。另有?次询问&#xff0c;每次询问一个价格?&#xff0c;问用若干张纸币是否可以恰好得到?。 【输入格式】 第一行两个整数?&#xff0c;?。 接下来一行?个整数&#xff…

对基于消息队列的Activiti异步执行器进行基准测试

一点历史 永不停息​​的一件事是&#xff0c;Activiti如何以惊人的规模在一些大型组织中使用。 过去&#xff0c;这导致了各种优化和重构&#xff0c;其中包括异步执行器-替换旧的作业执行器。 对于未启动的用户&#xff1a;这些执行器在流程实例中处理计时器和异步继续。 特别…

最大公约数最小公倍数

最大公约数&#xff1a;&#xff08;用辗转相除法&#xff09;int cd(int x, int y) { int m, n, t; if(x > y) {m x; n y; } else { m y; n x; } while(m % n ! 0) { t n; n m % n; m t; } return n; }最小公倍数 x*y/最大公约数。

ACM网站

中国&#xff1a; 南阳理工http://acm.nyist.net/JudgeOnline/problemset.php 浙江大学 http://acm.zju.edu.cn 北京大学 http://acm.pku.edu.cn/JudgeOnline 天津大学 http://acm.tju.edu.cn 厦门大学 http://acm.xmu.edu.cn/JudgeOnline 福州大学 http://acm.fzu.edu.c…

2020德勤面试开始了吗_2020公务员面试公告已出,5月28日开始面试

重磅&#xff01;上海市2020年度考试录用公务员职位报名及面试工作公告出了&#xff01;报岗时间&#xff1a;2020年5月11日10:00至5月15日18:00岗位调剂&#xff1a;2020年5月18日10:00至5月20日18:00面试时间&#xff1a;2020年5月28日至6月1日面试时需携带哪些证件和材料?答…

JavaScript 常用内置对象(字符串属性、Math对象、Array数组对象)

1.字符串属性<script>var test_var "I Iove you";console.log(test_var.charAt(3)) //charAt(n) &#xff1a;返回该字符串第 n 位的单个字符。&#xff08;从 0 开始计数&#xff09; console.log(test_var.charCodeAt(2)); //charCodeAt(n) &#xff1a;返回…

阿米洛键盘取消win_阿米洛花旦娘静电容V2键盘测评:不止是一把好看的键盘

文丨me王bigfun社区原文地址&#xff1a;【开箱/测评】阿米洛花旦娘静电容V2键盘&#xff0c;不止是一把好看的键盘 - bigfun序&#xff1a;我想要换一把好的键盘&#xff0c;因为这把雷柏的V500键盘已经跟了我4年&#xff0c;现在的它又老又丑&#xff0c;抚摸起来的手感还很生…

NY : 括号匹配问题

括号配对问题 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;3描述现在&#xff0c;有一行括号序列&#xff0c;请你检查这行括号是否配对。 输入第一行输入一个数N&#xff08;0<N<100&#xff09;,表示有N组测试数据。后面的N行输入多…

【代码笔记】Web-ionic-select

一&#xff0c;效果图。 二&#xff0c;代码。 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>Todo</title> <meta name"viewport" content"initial-scale1, maximum-scale1, user-scalableno…

adf开发_ADF:动态视图对象

adf开发今天&#xff0c;我想写有关动态视图对象的信息&#xff0c;该对象允许我在运行时更改其数据源&#xff08;SQL查询&#xff09;和属性。 我将使用oracle.jbo.ApplicationModule :: createViewObjectFromQueryStmt方法来解决此问题。 我将逐步介绍如何执行此操作 创建…

stm32f407能跑linux吗_跑步能跑进医院?那我该做跑步运动吗?想健康一点太难了...

跑步能跑进医院&#xff1f;那我该做跑步运动吗&#xff1f;想健康一点太难了&#xff0c;小编学生时期最喜欢的课程永远都是体育课&#xff0c;但最头疼的项目却是磨人的800米和1000米&#xff0c;那简直是我的的噩梦&#xff0c;近日&#xff0c;西安一名初中生跑步居然跑进了…

ACM进阶计划

ACM队不是为了一场比赛而存在的&#xff0c;为的是队员的整体提高。 大学期间&#xff0c;ACM队队员必须要学好的课程有&#xff1a; l C/C两种语言 l 高等数学 l 线性代数 l 数据结构 l 离散数学 l 数据库原理 l 操作系统原理 l 计算机组成原理 l 人工智能 l 编译原理 l 算法设…