【CF666E】Forensic Examination - 广义后缀自动机+线段树合并
广义SAM专题的最后一题了……呼
题意:
给出一个长度为$n$的串$S$和$m$个串$T_{1\cdots m}$,给出$q$个询问$l,r,pl,pr$,询问$S[pl\cdots pr]$在$T_l\cdots T_r$中哪个串出现次数最多,出现了多少次。
$1\leq n,q\leq 10^5,1\leq m,\sum|T|\leq 10^4$
串中只会出现小写字母
题解:
神题啊……放图镇楼
先对T串建出广义SAM,然后把S放到上面匹配,求出每个字符所代表的节点,那么每次查询就相当于求这一段字符在SAM上对应的节点的right集合包含的字符串的众数是哪个串,显然这是parent树上的一个子树众数问题;
考虑如何维护right集合在所有$T$中的出现次数,可以对每一个节点开一棵线段树,维护每个T串的出现次数的最大值,这样子在parent树上从下往上线段树合并即可求出right集合;
把询问离线按照右端点排序,把询问标记打在parent树上,最后dfs一遍合并+处理询问即可;
口胡起来不难但是写起来……超爽!
代码:
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<cmath> 7 #include<queue> 8 #define inf 2147483647 9 #define eps 1e-9 10 using namespace std; 11 typedef long long ll; 12 typedef double db; 13 struct task{ 14 int v,id; 15 task(){v=id=0;} 16 friend bool operator <(task a,task b){ 17 return a.v==b.v?a.id>b.id:a.v<b.v; 18 } 19 }ans[500001]; 20 struct qu{ 21 int l,r,ql,qr; 22 }q[500001]; 23 struct edge{ 24 int v,next; 25 }a[1000001]; 26 struct node{ 27 int ls,rs; 28 task v; 29 }t[4000001]; 30 int n,m,Q,len,ch,nw=1,tote=0,tot=1,rt=1,cnt=0,last,head[1000001],rts[1000001],son[1000001][26],fa[1000001],mx[1000001],f[1000001][20]; 31 vector<int>qrs[500001]; 32 vector<int>as[500001]; 33 char st[500001],tt[500001]; 34 void add(int u,int v){ 35 a[++tote].v=v; 36 a[tote].next=head[u]; 37 head[u]=tote; 38 } 39 void updata(int &u,int l,int r,int x){ 40 if(!u)u=++cnt; 41 if(l==r){ 42 t[u].v.v++; 43 t[u].v.id=x; 44 return; 45 } 46 int mid=(l+r)/2; 47 if(x<=mid)updata(t[u].ls,l,mid,x); 48 else updata(t[u].rs,mid+1,r,x); 49 t[u].v=max(t[t[u].ls].v,t[t[u].rs].v); 50 } 51 void merge(int &x,int y){ 52 if(!x||!y){ 53 x|=y; 54 return; 55 } 56 if(!t[x].ls&&!t[x].rs){ 57 t[x].v.v+=t[y].v.v; 58 return; 59 } 60 merge(t[x].ls,t[y].ls); 61 merge(t[x].rs,t[y].rs); 62 t[x].v=max(t[t[x].ls].v,t[t[x].rs].v); 63 } 64 task query(int u,int l,int r,int L,int R){ 65 if(L<=l&&r<=R){ 66 return t[u].v; 67 } 68 int mid=(l+r)/2; 69 task ret; 70 if(L<=mid)ret=max(ret,query(t[u].ls,l,mid,L,R)); 71 if(mid<R)ret=max(ret,query(t[u].rs,mid+1,r,L,R)); 72 return ret; 73 } 74 void extend(int ch){ 75 int p=last,np=++tot; 76 mx[np]=mx[p]+1; 77 for(;p&&!son[p][ch];p=fa[p])son[p][ch]=np; 78 if(!p)fa[np]=rt; 79 else{ 80 int q=son[p][ch]; 81 if(mx[q]==mx[p]+1)fa[np]=q; 82 else{ 83 int nq=++tot; 84 mx[nq]=mx[p]+1; 85 memcpy(son[nq],son[q],sizeof(son[q])); 86 fa[nq]=fa[q]; 87 fa[q]=fa[np]=nq; 88 for(;p&&son[p][ch]==q;p=fa[p])son[p][ch]=nq; 89 } 90 } 91 last=np; 92 } 93 void dfs(int u){ 94 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){ 95 int v=a[tmp].v; 96 dfs(v); 97 merge(rts[u],rts[v]); 98 } 99 for(int i=0,ii=as[u].size();i<ii;i++){ 100 ans[as[u][i]]=query(rts[u],1,m,q[as[u][i]].l,q[as[u][i]].r); 101 } 102 } 103 int main(){ 104 memset(head,-1,sizeof(head)); 105 scanf("%s%d",st+1,&m); 106 n=strlen(st+1); 107 for(int i=1;i<=m;i++){ 108 scanf("%s",tt); 109 len=strlen(tt); 110 last=rt; 111 for(int j=0;j<len;j++){ 112 extend(tt[j]-'a'); 113 updata(rts[last],1,m,i); 114 } 115 } 116 scanf("%d",&Q); 117 for(int i=1;i<=Q;i++){ 118 scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].ql,&q[i].qr); 119 qrs[q[i].qr].push_back(i); 120 } 121 for(int i=2;i<=tot;i++){ 122 f[i][0]=fa[i]; 123 add(fa[i],i); 124 } 125 for(int j=1;j<=19;j++){ 126 for(int i=1;i<=tot;i++){ 127 f[i][j]=f[f[i][j-1]][j-1]; 128 } 129 } 130 len=0; 131 for(int i=1;i<=n;i++){ 132 ch=st[i]-'a'; 133 for(;nw&&!son[nw][ch];)nw=fa[nw],len=mx[nw]; 134 if(!nw){ 135 nw=rt; 136 len=0; 137 }else{ 138 nw=son[nw][ch]; 139 len++; 140 for(int j=0,jj=qrs[i].size();j<jj;j++){ 141 int v=qrs[i][j]; 142 if(len>=q[v].qr-q[v].ql+1){ 143 int _nw=nw; 144 for(int k=19;k>=0;k--){ 145 if(mx[f[_nw][k]]>=q[v].qr-q[v].ql+1){ 146 _nw=f[_nw][k]; 147 } 148 } 149 as[_nw].push_back(v); 150 } 151 } 152 } 153 } 154 dfs(1); 155 for(int i=1;i<=Q;i++){ 156 if(!ans[i].v)ans[i].id=q[i].l; 157 printf("%d %d\n",ans[i].id,ans[i].v); 158 } 159 return 0; 160 }
转载于:https://www.cnblogs.com/dcdcbigbig/p/10160391.html
【CF666E】Forensic Examination - 广义后缀自动机+线段树合并相关推荐
- Codeforces.666E.Forensic Examination(广义后缀自动机 线段树合并)
题目链接 \(Description\) 给定串\(S\)和\(m\)个串\(T_i\).\(Q\)次询问,每次询问\(l,r,p_l,p_r\),求\(S[p_l\sim p_r]\)在\(T_l\ ...
- Codeforces.700E.Cool Slogans(后缀自动机 线段树合并 DP)
题目链接 \(Description\) 给定一个字符串\(s[1]\).一个字符串序列\(s[\ ]\)满足\(s[i]\)至少在\(s[i-1]\)中出现过两次(\(i\geq 2\)).求最大的 ...
- Codeforces 666E Forensic Examination SAM+权值线段树
第一次做这种\(SAM\)带权值线段树合并的题 然而\(zjq\)神犇看完题一顿狂码就做出来了 \(Orz\) 首先把所有串当成一个串建\(SAM\) 我们对\(SAM\)上每个点 建一棵权值线段树 ...
- luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分...
仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ...
- BZOJ 3277 串 BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析、启发式合并、线段树合并、主席树)...
标签那么长是因为做法太多了... 题目链接: (bzoj 3277) https://www.lydsy.com/JudgeOnline/problem.php?id=3277 (bzoj 3473) ...
- 【NOI2018】你的名字【后缀自动机】【可持久化线段树合并】【乱搞】
题意:给一个串 SSS,qqq 次询问,每次给定串 TTT 和 l,rl,rl,r ,求有多少个本质不同的串是 TTT 的子串而不是 Sl-rS_{l\dots r}Sl-r 的子串. ∣S∣≤5× ...
- 【bzoj5084】hashit 广义后缀自动机+树链的并+STL-set
题目描述 你有一个字符串S,一开始为空串,要求支持两种操作 在S后面加入字母C 删除S最后一个字母 问每次操作后S有多少个两两不同的连续子串 输入 一行一个字符串Q,表示对S的操作 如果第i个字母是小 ...
- [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)
题目描述 给一个小写字母字符串 S ,q 次询问每次给出 l,r ,求 s[l..r] 的 Border . Border: 对于给定的串 s ,最大的 i 使得 s[1..i] = s[|s|-i+ ...
- UOJ #395 BZOJ 5417 Luogu P4770 [NOI2018]你的名字 (后缀自动机、线段树合并)
NOI2019考前做NOI2018题.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=5417 (luogu) http ...
最新文章
- MPB:湖南师大尹佳组-​乳酸菌对酸和胆碱盐的耐受能力
- python 模拟微信浏览器请求_使用Chrome修改user agent模拟微信内置浏览器
- 比尔盖茨,马斯克、霍金都告诉你:为什么要警惕人工智能(中)
- jQuery动态改变图片显示大小(修改)
- 曾经采集朋友圈难倒多少Python大佬,今天手把手教你如何实现!
- c语言第一周项目,C语言第一周实战
- AI学习笔记(十)卷积神经网络
- 笔记本电脑开机后在桌面上没有计算机图标,电脑开机之后桌面上没有图标怎么处理...
- 使用MNIST数据集训练出来的模型预测自己手写数据
- Zookeeper配置项说明
- linux软件包管理思维导图,推荐五款管理工具(思维导图)
- Java自己编名字的百家姓罗列
- 欧拉-拉格朗日方程(Euler -Lagrange equation)
- 三维重建 | 单张彩色图像三维重建学习框架
- 6572 Phone call分析
- 用百度地图进行搜索周边的建筑,医院,餐厅,学校等。
- 【FreeRTOS】FreeRTOS学习笔记(3)— FreeRTOS任务与协程
- 随机计算(3)——Stochastic Circuit Synthesis by Cube Assignment
- 为什么反向传播更加高效
- mSystem:鸟枪法宏基因组测序之外我们还能做什么
热门文章
- NVisionXR_iOS教程五 —— 添加灯光渲染
- 《OpenGL编程指南(原书第9版)》——2.3 OpenGL着色语言概述
- CentOS 上snmp的安装和配置
- 我的Java开发学习之旅------求字符串中出现次数最多的字符串以及出现的次数...
- debian下apr-get isntall 出错提示用apt-get -f install问题
- extjs 网站首页table布局,秀一下
- 蓝桥杯 ADV-227 算法提高 11-1实现strcmp函数
- L1-015. 跟奥巴马一起画方块-PAT团体程序设计天梯赛GPLT
- 哪个计算机无法做到双屏显示,[工具/ PC]如何在计算机上实现双屏显示?
- JAVA 字符串格式化-String.format()的使用(转)