Description

给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串?

Input

第一行两个整数n,k。
接下来n行每行一个字符串。

Output

一行n个整数,第i个整数表示第i个字符串的答案。

Sample Input

3 1
abc
a
ab

Sample Output

6 1 3

HINT

对于 100% 的数据,1<=n,k<=10^5,所有字符串总长不超过10^5,字符串只包含小写字母。

Solution

加分隔符建出后缀数组,考虑每个后缀的所有前缀,这样就能考虑到所有的子串了。

对于每一个后缀,二分前缀的长度,

然后在二分里面再通过二分左右端点加$ST$表确定$lcp$大于等于之前二分前缀长度的后缀排名区间,

最后用主席树查询一下区间颜色个数是否超过k就行了。查询方法参照HH的项链主席树做法。

话说字符串拼接完了长度是$2\times 10^5$不是$10^5$……数组开小真是太真实了。

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#define N (200009)
#define LL long long
using namespace std; struct Sgt{int ls,rs,val;}Segt[N*];
int sgt_num,Root[N],a[N],Next[N];
int n,m=,c,k;
int wa[N],wb[N],wt[N];
int Rank[N],SA[N],Height[N];
int ST[N][],LOG2[N];
int ID[N],id_num,End[N];
LL Ans[N];
char r[N],s[N]; bool cmp(int *y,int a,int b,int k)
{
int arank1=y[a];
int brank1=y[b];
int arank2=a+k>=n?-:y[a+k];
int brank2=b+k>=n?-:y[b+k];
return arank1==brank1 && arank2==brank2;
} void Build_SA()
{
int *x=wa,*y=wb;
for (int i=; i<m; ++i) wt[i]=;
for (int i=; i<n; ++i) ++wt[x[i]=r[i]];
for (int i=; i<m; ++i) wt[i]+=wt[i-];
for (int i=n-; i>=; --i) SA[--wt[x[i]]]=i; for (int j=; j<=n; j<<=)
{
int p=;
for (int i=n-j; i<n; ++i) y[p++]=i;
for (int i=; i<n; ++i) if (SA[i]>=j) y[p++]=SA[i]-j; for (int i=; i<m; ++i) wt[i]=;
for (int i=; i<n; ++i) ++wt[x[y[i]]];
for (int i=; i<m; ++i) wt[i]+=wt[i-];
for (int i=n-; i>=; --i) SA[--wt[x[y[i]]]]=y[i]; m=; swap(x,y); x[SA[]]=;
for (int i=; i<n; ++i)
x[SA[i]]=cmp(y,SA[i],SA[i-],j)?m-:m++;
if (m>=n) break;
}
} void Build_Height()
{
for (int i=; i<n; ++i) Rank[SA[i]]=i;
int k=;
for (int i=; i<n; ++i)
{
if (!Rank[i]) continue;
if (k) --k;
int j=SA[Rank[i]-];
while (r[i+k]==r[j+k]) ++k;
Height[Rank[i]]=k;
}
} void Build_ST()
{
for (int i=; i<=n; ++i) LOG2[i]=LOG2[i>>]+;
for (int i=; i<n; ++i) ST[i][]=Height[i];
for (int j=; j<=; ++j)
for (int i=; i+(<<j)-<n; ++i)
ST[i][j]=min(ST[i][j-],ST[i+(<<j-)][j-]);
} int Query(int l,int r)
{
int k=LOG2[r-l+];
return min(ST[l][k],ST[r-(<<k)+][k]);
} int Update(int pre,int l,int r,int x)
{
int now=++sgt_num;
Segt[now]=Segt[pre]; Segt[now].val++;
if (l==r) return now;
int mid=(l+r)>>;
if (x<=mid) Segt[now].ls=Update(Segt[now].ls,l,mid,x);
else Segt[now].rs=Update(Segt[now].rs,mid+,r,x);
return now;
} int Query(int u,int v,int l,int r,int l1,int r1)
{
if (l>r1 || r<l1) return ;
if (l1<=l && r<=r1) return Segt[v].val-Segt[u].val;
int mid=(l+r)>>;
return Query(Segt[u].ls,Segt[v].ls,l,mid,l1,r1)+Query(Segt[u].rs,Segt[v].rs,mid+,r,l1,r1);
} void Build_CT()
{
for (int i=; i<=c; ++i) Next[i]=n;
for (int i=n-; i>=; --i) a[i+]=Next[ID[SA[i]]], Next[ID[SA[i]]]=i;
for (int i=; i<=n; ++i) Root[i]=Update(Root[i-],,n,a[i]);
} bool check(int p,int lim)
{
int l,r,L,R;
l=,r=p-,L=p;
while (l<=r)
{
int mid=(l+r)>>,lcp=Query(mid+,p);
if (lcp>=lim) L=mid, r=mid-;
else l=mid+;
}
l=p+,r=n-,R=p;
while (l<=r)
{
int mid=(l+r)>>,lcp=Query(p+,mid);
if (lcp>=lim) R=mid, l=mid+;
else r=mid-;
}
return Query(Root[L],Root[R+],,n,R+,n)>=k;
} int main()
{
scanf("%d%d",&c,&k);
for (int i=; i<=c; ++i)
{
scanf("%s",s);
for (int j=,l=strlen(s); j<l; ++j)
ID[n]=i, r[n++]=s[j];
End[i]=n; ID[n]=i, r[n++]='#';
}
Build_SA(); Build_Height();
Build_ST(); Build_CT();
for (int i=; i<n; ++i)
{
if (r[SA[i]]=='#') continue;
int l=,r=End[ID[SA[i]]]-SA[i],ans=;
while (l<=r)
{
int mid=(l+r)>>;
if (check(i,mid)) ans=mid, l=mid+;
else r=mid-;
}
Ans[ID[SA[i]]]+=ans;
}
for (int i=; i<=c; ++i)
printf("%lld ",Ans[i]);
}

BZOJ3473:字符串(后缀数组,主席树,二分,ST表)的更多相关文章

  1. BZOJ4556:[TJOI\HEOI2016]字符串(后缀数组,主席树,二分,ST表)

    Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱 ...

  2. BZOJ4556 [Tjoi2016&Heoi2016]字符串 【后缀数组 + 主席树 + 二分 + ST表】

    题目 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱子拿到礼物,升职 ...

  3. P4094 [HEOI2016/TJOI2016]字符串 后缀数组+主席树+二分答案

    $ \color{#0066ff}{ 题目描述 }$ 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须 ...

  4. [HEOI2016] 字符串 - 后缀数组,主席树,ST表,二分

    [HEOI2016] 字符串 Description 给定一个字符串 \(S\), 有 \(m\) 个询问,每个询问给定参数 \((a,b,c,d)\) ,求 \(s[a..b]\) 的子串与 \(s ...

  5. [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MB Description 佳媛姐姐过生日的时候,她的小 ...

  6. bzoj 4556 [Tjoi2016&Heoi2016]字符串——后缀数组+主席树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4556 本来只要查 ht[ ] 数组上的前驱和后继就行,但有长度的限制.可以二分答案解决!然后 ...

  7. bzoj 4556 字符串 —— 后缀数组+主席树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4556 就是找一个 rk 在一段区间内的前驱和后继: 由于 LCP 还有区间长度的限制,所以可 ...

  8. LOJ_#2720. 「NOI2018」你的名字 _后缀数组+主席树+倍增

    题面: https://loj.ac/problem/2720 考虑枚举T串的每个后缀i,我们要做两件事. 一.统计有多少子串[i,j]在S中要求位置出现. 二.去重. 第二步好做,相当于在后缀数组上 ...

  9. BZOJ3166 [Heoi2013]Alo 【可持久化trie树 + 二分 + ST表】

    题目 Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG , 如名字所见,到处充满了数学的谜题. 现在你拥有n颗宝石,每颗宝石 ...

随机推荐

  1. SQL Server ——用 join on 连接多个表

    select * from table1 inner join table2 on table1.id=table2.id 其实 INNER JOIN ……ON的语法格式可以概括为: FROM ((( ...

  2. 一个人的旅行(hdu2066)Dijkstra算法模版

    一个人的旅行 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  3. Java虚拟机 - Class类文件结构

    [深入Java虚拟机]之二:Class类文件结构 平台无关性 Java是与平台无关的语言,这得益于Java源代码编译后生成的存储字节码的文件,即Class文件,以及Java虚拟机的实现.不仅使用Jav ...

  4. 获取物化视图定义语句的SQL

    老系统里总有人用物化视图,然后新同事们就得去FixBug 然后就遇到怎么查看物化视图定义语句的问题了 分享下,祝顺利! DBA权限下执行: select dbms_metadata.get_ddl(' ...

  5. 设计模式(9)--Composite(组合模式)--结构型

    1.模式定义: 组合模式属于对象的结构模式,有时又叫做“部分——整体”模式.组合模式将对象组织到树结构中,可以用来描述整体与部分的关系.组合模式可以使客户端将单纯元素与复合元素同等看待. 2.模式特点 ...

  6. jQuery复选框全选和全选取消

    jQuery(".salaryIds").each(function(){ if(jQuery("#salaryIds").attr("checked ...

  7. 转:PHPStorm+XDebug进行调试图文教程

    原文:PHPStorm+XDebug进行调试图文教程 一.XDebug安装配置 (1)下载XDebug下载地址:http://www.xdebug.org/必须下载跟机器上安装的php匹配的版本才行. ...

  8. img,a,锚链接,超链接

    1.图片标签:img,单标签 图片属性: src(source): 图片的来源(路径),可以放置本地图片,也可以放网上的图片的url地址 title: 当鼠标停留在图片上的时候,显示提示的文字 alt ...

  9. css设计并排布局

    css code form#reset_password ul { list-style: none; margin: 0 0 20px 200px; padding:; } form#reset_p ...

  10. 【three.js练习程序】创建简单物理地形

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...