题目分析:

用"$"连接后缀数组,然后做一个主席树求区间内不同的数的个数。二分一个前缀长度再在主席树上求不同的数的个数。

代码:

 #include<bits/stdc++.h>
using namespace std; const int maxn = ;
const int N = ; int m,n,k;
string hmk[maxn],str;
int sum[maxn]; int sa[maxn],rk[maxn],X[maxn],Y[maxn];
int height[maxn],h[maxn],RMQ[maxn][],Tnum;
long long ans[maxn]; struct node{
int ch[],sum;
}CMT[maxn*]; int chk(int x,int k){
return rk[sa[x]]==rk[sa[x-]]&&rk[sa[x]+(<<k)]==rk[sa[x-]+(<<k)];
} void getsa(){
for(int i=;i<n;i++) X[str[i]]++;
for(int i=;i<=N;i++) X[i] += X[i-];
for(int i=n-;i>=;i--) sa[X[str[i]]--] = i;
for(int i = , num = ;i <= n;i++)
rk[sa[i]] = (str[sa[i]] == str[sa[i-]]?num:++num);
rk[sa[]] = ;
for(int k=;(<<k-)<=n;k++){
for(int i=;i<=N;i++) X[i] = ;
for(int i=n-(<<k-);i<n;i++) Y[i-n+(<<k-)+]=i;
for(int i=,j=(<<k-)+;i<=n;i++)
if(sa[i]>=(<<k-))Y[j++]=sa[i]-(<<k-);
for(int i=;i<n;i++) X[rk[i]]++;
for(int i=;i<=N;i++) X[i]+=X[i-];
for(int i=n;i>=;i--) sa[X[rk[Y[i]]]--] = Y[i];
int num = ; Y[sa[]] = ;
for(int i=;i<=n;i++) Y[sa[i]] = (chk(i,k-)?num:++num);
for(int i=;i<n;i++) rk[i] = Y[i];
if(num == n) break;
}
}
void getheight(){
for(int i=;i<n;i++){
if(i) h[i] = max(,h[i-]-); else h[i] = ;
if(rk[i] == ) continue;
int comp = sa[rk[i]-];
while(str[comp+h[i]] == str[i+h[i]])h[i]++;
}
for(int i=;i<n;i++) height[rk[i]] = h[i];
for(int i=;i<=n;i++) RMQ[i][] = height[i];
for(int k=;(<<k)<=n;k++){
for(int i=;i<=n;i++){
if(i+(<<k-)>n) RMQ[i][k]=RMQ[i][k-];
else RMQ[i][k] = min(RMQ[i][k-],RMQ[i+(<<k-)][k-]);
}
}
} int pww[maxn];
int getLCP(int L,int R){
if(L == R) return n-sa[L];
L++;
int k = pww[R-L+];
return min(RMQ[L][k],RMQ[R-(<<k)+][k]);
} void build_empty_tree(int now,int tl,int tr){
if(tl == tr) return;
int mid = (tl+tr)/;
Tnum++; CMT[now].ch[] = Tnum;
build_empty_tree(Tnum,tl,mid);
Tnum++; CMT[now].ch[] = Tnum;
build_empty_tree(Tnum,mid+,tr);
} void Modify(int lst,int now,int tl,int tr,int pos,int dt){
CMT[now] = CMT[lst];
if(tl == tr){CMT[now].sum += dt;}
else{
int mid = (tl+tr)/;
if(pos <= mid){
CMT[now].ch[] = ++Tnum;
Modify(CMT[lst].ch[],Tnum,tl,mid,pos,dt);
}else{
CMT[now].ch[] = ++Tnum;
Modify(CMT[lst].ch[],Tnum,mid+,tr,pos,dt);
}
CMT[now].sum += dt;
}
} int imp[maxn],his[maxn];
void build_CMT(){
his[] = ;
for(int i=;i<=n;i++){
if(imp[sum[sa[i]]]){
int z = ++Tnum;
Modify(his[i-],z,,n,imp[sum[sa[i]]],-);
his[i] = ++Tnum; imp[sum[sa[i]]] = i;
Modify(z,his[i],,n,i,);
}else{
his[i] = ++Tnum; imp[sum[sa[i]]] = i;
Modify(his[i-],his[i],,n,i,);
}
}
} int query(int now,int tl,int tr,int l,int r){
if(tl >= l && tr <= r) return CMT[now].sum;
if(tl > r || tr < l) return ;
int mid = (tl+tr)/;
int as=query(CMT[now].ch[],tl,mid,l,r)+query(CMT[now].ch[],mid+,tr,l,r);
return as;
} int rgt[maxn];
void work(){
getsa();
getheight();
sum[n] = ;rgt[n] = n;
for(int i=n-;i>=;i--){
sum[i] = sum[i+]+(str[i] == '$');
if(str[i] == '$') rgt[i] = i;
else rgt[i] = rgt[i+];
}
Tnum = ;
build_empty_tree(,,n);
build_CMT();
for(int i=m;i<=n;i++){
int l = ,r = rgt[sa[i]]-sa[i];
while(l < r){
int mid = (l+r+)/;
int al = ,ar = i;
while(al < ar){
int midd = (al+ar)/;
if(getLCP(midd,i) >= mid) ar = midd;
else al = midd+;
}
int tl = i,tr = n;
while(tl < tr){
int midd = (tl+tr+)/;
if(getLCP(i,midd) >= mid) tl = midd;
else tr = midd-;
}
int mmp = query(his[tl],,n,al,tl);
if(mmp >= k) l = mid;
else r = mid-;
}
ans[m-sum[sa[i]]+] += l;
}
for(int i=;i<=m;i++) printf("%lld ",ans[i]);
} int main(){
ios::sync_with_stdio(false);
cin.tie();
cin >> m >> k;
for(int i=;i<=m;i++) cin >> hmk[i];
for(int i=;i<m;i++) str += hmk[i],str += '$';
str += hmk[m];
n = str.length();
pww[] = ;
for(int i=;i<=n;i++) pww[i] = pww[i/]+;
work();
return ;
}

BZOJ3277 串 【后缀数组】【二分答案】【主席树】的更多相关文章

  1. BZOJ3277 串(后缀数组+二分答案+主席树)

    因为不会SAM,考虑SA.将所有串连起来并加分隔符,每次考虑计算以某个位置开始的子串有多少个合法. 对此首先二分答案,找到名次数组上的一个区间,那么只需要统计有多少个所给串在该区间内出现就可以了.这是 ...

  2. BZOJ 4556: [Tjoi2016&Heoi2016]字符串(后缀数组 + 二分答案 + 主席树 + ST表 or 后缀数组 + 暴力)

    题意 一个长为 \(n\) 的字符串 \(s\),和 \(m\) 个询问.每次询问有 \(4\) 个参数分别为 \(a,b,c,d\). 要你告诉它 \(s[a...b]\) 中的所有子串 和 \(s ...

  3. bzoj3277 串 (后缀数组+二分答案+ST表)

    常见操作:先把所有串都连到一起,但中间加上一个特殊的符号(不能在原串中/出现过)作为分割 由于全部的子串就等于所有后缀的所有前缀,那我们对于每一个后缀,去求一个最长的前缀,来满足这个前缀在至少K个原串 ...

  4. BZOJ 4556 [Tjoi2016&Heoi2016]字符串 ——后缀数组 ST表 主席树 二分答案

    Solution 1: 后缀数组暴力大法好 #include <map> #include <cmath> #include <queue> #include &l ...

  5. BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案

    BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description          给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l        读入单 ...

  6. BZOJ5343: [Ctsc2018]混合果汁 二分答案+主席树

    分析: 整体二分或二分答案+主席树,反正没有要求强制在线,两个都可以做... 贪心还是比较显然的,那么就是找前K大的和...和CQOI的任务查询系统很像 附上代码: #include <cstd ...

  7. BZOJ_5343_[Ctsc2018]混合果汁_二分答案+主席树

    BZOJ_5343_[Ctsc2018]混合果汁_二分答案+主席树 题意:给出每个果汁的价格p,美味度d,最多能放的体积l.定义果汁混合后的美味度为果汁的美味度的最小值. m次询问,要求花费不大于g, ...

  8. Poj 1743 Musical Theme(后缀数组+二分答案)

    Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...

  9. Poj 3261 Milk Patterns(后缀数组+二分答案)

    Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...

  10. 2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)

    K-th Closest Distance 题目传送门 解题思路 二分答案+主席树 先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明 ...

随机推荐

  1. 初次接触CSS变量

    本文的目的主要是展示CSS变量是如何工作的.随着Web应用程序变得越来越大,CSS变得越来越大,越来越多,而且很多时候都很乱,在良好的上下文中使用CSS变量,为您提供重用和轻松更改重复出现的CSS属性 ...

  2. JS实现一个v-if

    // 获取dom var el = document.getElementById('root'); console.log(el); // 遍历dom function dealNode(el) { ...

  3. Jquery遍历之获取子级元素、同级元素和父级元素

    Jquery遍历之获取子级元素.同级元素和父级元素 Jquery的遍历,其实就当前位置的元素相对于其他元素的位置的关系进行查找或选取HTML元素.以某项选择开始,并沿着这条线进行移动,或向上(父级). ...

  4. Django Rest framework基础使用之Request/Response

    1.Request restframework提供了一个Request对象(rest_framework.request.Request) Request对象继承了Django默认的HttpReque ...

  5. Leetcode 665. Non-decreasing Array(Easy)

    Given an array with n integers, your task is to check if it could become non-decreasing by modifying ...

  6. R语言

    什么是R语言编程? R语言是一种用于统计分析和为此目的创建图形的编程语言.不是数据类型,它具有用于计算的数据对象.它用于数据挖掘,回归分析,概率估计等领域,使用其中可用的许多软件包. R语言中的不同数 ...

  7. iOS基于B站的IJKPlayer框架的流媒体探究

    阅读数:6555 学习交流及技术讨论可新浪微博关注:极客James 一.流媒体 流媒体技术从传输形式上可以分为:渐进式下载和实施流媒体. 1.渐进式下载 它是介于实时播放和本地播放之间的一种播放方式, ...

  8. Python之参数类型、变量

    一.参数类型 (一)形参与实参 要使用局部变量时,只能通过return的方式返回 def my(name): #函数体 return name my('lrx') #name是形参,lrx是实参 不写 ...

  9. 启动Tomcat的时候8080被占用

    异常来源:启动Tomcat服务器报错: Several ports (8080, 8009) required by Tomcat v7.0 Server at localhost are alrea ...

  10. Oracle NVL空值处理函数

    --NVL空值处理函数 --需求:显示价格表中业主类型ID为1的价格记录 如果上限值为null,则显示9999999 ) from dual; select * from t_pricetable ) ...