BZOJ3277 串 【后缀数组】【二分答案】【主席树】
题目分析:
用"$"连接后缀数组,然后做一个主席树求区间内不同的数的个数。二分一个前缀长度再在主席树上求不同的数的个数。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 132000; 5 const int N = 130000; 6 7 int m,n,k; 8 string hmk[maxn],str; 9 int sum[maxn]; 10 11 int sa[maxn],rk[maxn],X[maxn],Y[maxn]; 12 int height[maxn],h[maxn],RMQ[maxn][20],Tnum; 13 long long ans[maxn]; 14 15 struct node{ 16 int ch[2],sum; 17 }CMT[maxn*35]; 18 19 int chk(int x,int k){ 20 return rk[sa[x]]==rk[sa[x-1]]&&rk[sa[x]+(1<<k)]==rk[sa[x-1]+(1<<k)]; 21 } 22 23 void getsa(){ 24 for(int i=0;i<n;i++) X[str[i]]++; 25 for(int i=1;i<=N;i++) X[i] += X[i-1]; 26 for(int i=n-1;i>=0;i--) sa[X[str[i]]--] = i; 27 for(int i = 2, num = 1;i <= n;i++) 28 rk[sa[i]] = (str[sa[i]] == str[sa[i-1]]?num:++num); 29 rk[sa[1]] = 1; 30 for(int k=1;(1<<k-1)<=n;k++){ 31 for(int i=1;i<=N;i++) X[i] = 0; 32 for(int i=n-(1<<k-1);i<n;i++) Y[i-n+(1<<k-1)+1]=i; 33 for(int i=1,j=(1<<k-1)+1;i<=n;i++) 34 if(sa[i]>=(1<<k-1))Y[j++]=sa[i]-(1<<k-1); 35 for(int i=0;i<n;i++) X[rk[i]]++; 36 for(int i=1;i<=N;i++) X[i]+=X[i-1]; 37 for(int i=n;i>=1;i--) sa[X[rk[Y[i]]]--] = Y[i]; 38 int num = 1; Y[sa[1]] = 1; 39 for(int i=2;i<=n;i++) Y[sa[i]] = (chk(i,k-1)?num:++num); 40 for(int i=0;i<n;i++) rk[i] = Y[i]; 41 if(num == n) break; 42 } 43 } 44 void getheight(){ 45 for(int i=0;i<n;i++){ 46 if(i) h[i] = max(0,h[i-1]-1); else h[i] = 0; 47 if(rk[i] == 1) continue; 48 int comp = sa[rk[i]-1]; 49 while(str[comp+h[i]] == str[i+h[i]])h[i]++; 50 } 51 for(int i=0;i<n;i++) height[rk[i]] = h[i]; 52 for(int i=1;i<=n;i++) RMQ[i][0] = height[i]; 53 for(int k=1;(1<<k)<=n;k++){ 54 for(int i=1;i<=n;i++){ 55 if(i+(1<<k-1)>n) RMQ[i][k]=RMQ[i][k-1]; 56 else RMQ[i][k] = min(RMQ[i][k-1],RMQ[i+(1<<k-1)][k-1]); 57 } 58 } 59 } 60 61 int pww[maxn]; 62 int getLCP(int L,int R){ 63 if(L == R) return n-sa[L]; 64 L++; 65 int k = pww[R-L+1]; 66 return min(RMQ[L][k],RMQ[R-(1<<k)+1][k]); 67 } 68 69 void build_empty_tree(int now,int tl,int tr){ 70 if(tl == tr) return; 71 int mid = (tl+tr)/2; 72 Tnum++; CMT[now].ch[0] = Tnum; 73 build_empty_tree(Tnum,tl,mid); 74 Tnum++; CMT[now].ch[1] = Tnum; 75 build_empty_tree(Tnum,mid+1,tr); 76 } 77 78 void Modify(int lst,int now,int tl,int tr,int pos,int dt){ 79 CMT[now] = CMT[lst]; 80 if(tl == tr){CMT[now].sum += dt;} 81 else{ 82 int mid = (tl+tr)/2; 83 if(pos <= mid){ 84 CMT[now].ch[0] = ++Tnum; 85 Modify(CMT[lst].ch[0],Tnum,tl,mid,pos,dt); 86 }else{ 87 CMT[now].ch[1] = ++Tnum; 88 Modify(CMT[lst].ch[1],Tnum,mid+1,tr,pos,dt); 89 } 90 CMT[now].sum += dt; 91 } 92 } 93 94 int imp[maxn],his[maxn]; 95 void build_CMT(){ 96 his[0] = 1; 97 for(int i=1;i<=n;i++){ 98 if(imp[sum[sa[i]]]){ 99 int z = ++Tnum; 100 Modify(his[i-1],z,1,n,imp[sum[sa[i]]],-1); 101 his[i] = ++Tnum; imp[sum[sa[i]]] = i; 102 Modify(z,his[i],1,n,i,1); 103 }else{ 104 his[i] = ++Tnum; imp[sum[sa[i]]] = i; 105 Modify(his[i-1],his[i],1,n,i,1); 106 } 107 } 108 } 109 110 int query(int now,int tl,int tr,int l,int r){ 111 if(tl >= l && tr <= r) return CMT[now].sum; 112 if(tl > r || tr < l) return 0; 113 int mid = (tl+tr)/2; 114 int as=query(CMT[now].ch[0],tl,mid,l,r)+query(CMT[now].ch[1],mid+1,tr,l,r); 115 return as; 116 } 117 118 int rgt[maxn]; 119 void work(){ 120 getsa(); 121 getheight(); 122 sum[n] = 1;rgt[n] = n; 123 for(int i=n-1;i>=0;i--){ 124 sum[i] = sum[i+1]+(str[i] == '$'); 125 if(str[i] == '$') rgt[i] = i; 126 else rgt[i] = rgt[i+1]; 127 } 128 Tnum = 1; 129 build_empty_tree(1,1,n); 130 build_CMT(); 131 for(int i=m;i<=n;i++){ 132 int l = 0,r = rgt[sa[i]]-sa[i]; 133 while(l < r){ 134 int mid = (l+r+1)/2; 135 int al = 1,ar = i; 136 while(al < ar){ 137 int midd = (al+ar)/2; 138 if(getLCP(midd,i) >= mid) ar = midd; 139 else al = midd+1; 140 } 141 int tl = i,tr = n; 142 while(tl < tr){ 143 int midd = (tl+tr+1)/2; 144 if(getLCP(i,midd) >= mid) tl = midd; 145 else tr = midd-1; 146 } 147 int mmp = query(his[tl],1,n,al,tl); 148 if(mmp >= k) l = mid; 149 else r = mid-1; 150 } 151 ans[m-sum[sa[i]]+1] += l; 152 } 153 for(int i=1;i<=m;i++) printf("%lld ",ans[i]); 154 } 155 156 int main(){ 157 ios::sync_with_stdio(false); 158 cin.tie(0); 159 cin >> m >> k; 160 for(int i=1;i<=m;i++) cin >> hmk[i]; 161 for(int i=1;i<m;i++) str += hmk[i],str += '$'; 162 str += hmk[m]; 163 n = str.length(); 164 pww[1] = 0; 165 for(int i=2;i<=n;i++) pww[i] = pww[i/2]+1; 166 work(); 167 return 0; 168 }
转载于:https://www.cnblogs.com/Menhera/p/10102070.html
BZOJ3277 串 【后缀数组】【二分答案】【主席树】相关推荐
- bzoj3277 串 (后缀数组+二分答案+ST表)
常见操作:先把所有串都连到一起,但中间加上一个特殊的符号(不能在原串中/出现过)作为分割 由于全部的子串就等于所有后缀的所有前缀,那我们对于每一个后缀,去求一个最长的前缀,来满足这个前缀在至少K个原串 ...
- [BZOJ4310]跳蚤-后缀数组-二分答案
跳蚤 Description 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究.首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择 ...
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分答案)
[题目链接] http://www.spoj.pl/problems/PHRASES/ [题目大意] 求在每个字符串中出现至少两次的最长的子串 [题解] 注意到这么几个关键点:最长,至少两次,每个字符 ...
- BZOJ3998 TJOI2015弦论(后缀数组+二分答案)
先看t=1的情况.显然得求出SA(因为我不会SAM).我们一位位地确定答案.设填到了第len位,二分这一位填什么之后,在已经确定的答案所在的范围(SA上的某段区间)内二分,找到最后一个小于当前串的后缀 ...
- codefores 204E. Little Elephant and Strings(后缀数组,RMQ求lcp,二分,主席树)
题目链接 E. Little Elephant and Strings time limit per test3 seconds memory limit per test256 megabytes ...
- [2020.11.26NOIP模拟赛]勇者的后缀【SA,RMQ,主席树,二分】
正题 题目链接:https://www.luogu.com.cn/problem/U142356?contestId=37784 题目大意 一个字符串,询问给出(x,l,r)(x,l,r)(x,l,r ...
- L3-002 堆栈 树状数组+二分答案
题目详情点击这里 思路:用std::stack来表示题目中说的栈,现在关键问题就是如何找到中位数. 可以用二分答案+树状数组的方法 由于每个元素最大不超过1e5,因此开一个大小为1e5的树状数组来存储 ...
- 洛谷 P4094 [HEOI2016/TJOI2016]字符串 后缀数组+二分+主席树
题目链接 后缀数组 题目分析: sa[i] – 第i小的后缀的编号 rank[i] --编号为i的后缀排第几: height[i] – 第i和第i-1的最长lcp最长公共前缀: 1.二分答案,答案肯定 ...
- 洛谷 P2468 粟粟的书架 二分(主席树+前缀和)
传送~:https://www.luogu.org/problem/P2468 看了一下数据也发现是两道题,后边当他是一个序列(n==1)的时候直接主席树二分区间前k大和就行了 但是有一个细节我觉得就 ...
- HDU - 5030 Rabbit's String(后缀数组+二分)
题目链接:点击查看 题目大意:给出一个字符串,现在要求将其分为不大于k个连续的子串,对于每个子串求出字典序最大的子串,现在要求所有子串的最大子串的最大值最小,输出这个最大子串 题目分析:最大值最小,标 ...
最新文章
- 读农民工兄弟学C#文章后的感觉
- CTFshow 反序列化 web267
- 梯度下降法原理及实现
- SemSorGrid4Env
- 10月16日培训日记
- 数学--数论--快速幂--最大公约数--位运算模板
- 容器编排技术 -- Init 容器
- 【转载】用平常语言介绍神经网络
- 工程数学(数值分析)第三讲:求解线性代数方程组
- 牛客网暑期ACM多校训练营(第五场): F. take(期望+线段树)
- 如何在Linux中使用netstat命令
- Angular4记账webApp练手项目之四(在Angular4项目中用echarts绘制图表)
- 史上最全的黑苹果系统「MacOS」安装教程,小白也能秒掌握!
- linux虚拟实验室关闭了,Linux在线虚拟云实验室,提升RHCE考试通过率
- Win7系统如何安装声卡驱动
- ss和netstat的区别
- DSP你都不知道是啥,还好意思说自己学过嵌入式?
- 主元分析法 matlab,数值分析实习作业之不选主元法高斯分解(Matlab)
- C#获取目录下所有文件的列表——最白话,手把手教你做系列。
- 计算机网络分代核心的属性,计算机网络开发专业核心能力题库-操作