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

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #define N (200009)
  5 #define LL long long
  6 using namespace std;
  7
  8 struct Sgt{int ls,rs,val;}Segt[N*18];
  9 int sgt_num,Root[N],a[N],Next[N];
 10 int n,m=125,c,k;
 11 int wa[N],wb[N],wt[N];
 12 int Rank[N],SA[N],Height[N];
 13 int ST[N][18],LOG2[N];
 14 int ID[N],id_num,End[N];
 15 LL Ans[N];
 16 char r[N],s[N];
 17
 18 bool cmp(int *y,int a,int b,int k)
 19 {
 20     int arank1=y[a];
 21     int brank1=y[b];
 22     int arank2=a+k>=n?-1:y[a+k];
 23     int brank2=b+k>=n?-1:y[b+k];
 24     return arank1==brank1 && arank2==brank2;
 25 }
 26
 27 void Build_SA()
 28 {
 29     int *x=wa,*y=wb;
 30     for (int i=0; i<m; ++i) wt[i]=0;
 31     for (int i=0; i<n; ++i) ++wt[x[i]=r[i]];
 32     for (int i=1; i<m; ++i) wt[i]+=wt[i-1];
 33     for (int i=n-1; i>=0; --i) SA[--wt[x[i]]]=i;
 34
 35     for (int j=1; j<=n; j<<=1)
 36     {
 37         int p=0;
 38         for (int i=n-j; i<n; ++i) y[p++]=i;
 39         for (int i=0; i<n; ++i) if (SA[i]>=j) y[p++]=SA[i]-j;
 40
 41         for (int i=0; i<m; ++i) wt[i]=0;
 42         for (int i=0; i<n; ++i) ++wt[x[y[i]]];
 43         for (int i=1; i<m; ++i) wt[i]+=wt[i-1];
 44         for (int i=n-1; i>=0; --i) SA[--wt[x[y[i]]]]=y[i];
 45
 46         m=1; swap(x,y); x[SA[0]]=0;
 47         for (int i=1; i<n; ++i)
 48             x[SA[i]]=cmp(y,SA[i],SA[i-1],j)?m-1:m++;
 49         if (m>=n) break;
 50     }
 51 }
 52
 53 void Build_Height()
 54 {
 55     for (int i=0; i<n; ++i) Rank[SA[i]]=i;
 56     int k=0;
 57     for (int i=0; i<n; ++i)
 58     {
 59         if (!Rank[i]) continue;
 60         if (k) --k;
 61         int j=SA[Rank[i]-1];
 62         while (r[i+k]==r[j+k]) ++k;
 63         Height[Rank[i]]=k;
 64     }
 65 }
 66
 67 void Build_ST()
 68 {
 69     for (int i=2; i<=n; ++i) LOG2[i]=LOG2[i>>1]+1;
 70     for (int i=0; i<n; ++i) ST[i][0]=Height[i];
 71     for (int j=1; j<=18; ++j)
 72         for (int i=0; i+(1<<j)-1<n; ++i)
 73             ST[i][j]=min(ST[i][j-1],ST[i+(1<<j-1)][j-1]);
 74 }
 75
 76 int Query(int l,int r)
 77 {
 78     int k=LOG2[r-l+1];
 79     return min(ST[l][k],ST[r-(1<<k)+1][k]);
 80 }
 81
 82 int Update(int pre,int l,int r,int x)
 83 {
 84     int now=++sgt_num;
 85     Segt[now]=Segt[pre]; Segt[now].val++;
 86     if (l==r) return now;
 87     int mid=(l+r)>>1;
 88     if (x<=mid) Segt[now].ls=Update(Segt[now].ls,l,mid,x);
 89     else Segt[now].rs=Update(Segt[now].rs,mid+1,r,x);
 90     return now;
 91 }
 92
 93 int Query(int u,int v,int l,int r,int l1,int r1)
 94 {
 95     if (l>r1 || r<l1) return 0;
 96     if (l1<=l && r<=r1) return Segt[v].val-Segt[u].val;
 97     int mid=(l+r)>>1;
 98     return Query(Segt[u].ls,Segt[v].ls,l,mid,l1,r1)+Query(Segt[u].rs,Segt[v].rs,mid+1,r,l1,r1);
 99 }
100
101 void Build_CT()
102 {
103     for (int i=1; i<=c; ++i) Next[i]=n;
104     for (int i=n-1; i>=0; --i) a[i+1]=Next[ID[SA[i]]], Next[ID[SA[i]]]=i;
105     for (int i=1; i<=n; ++i) Root[i]=Update(Root[i-1],0,n,a[i]);
106 }
107
108 bool check(int p,int lim)
109 {
110     int l,r,L,R;
111     l=0,r=p-1,L=p;
112     while (l<=r)
113     {
114         int mid=(l+r)>>1,lcp=Query(mid+1,p);
115         if (lcp>=lim) L=mid, r=mid-1;
116         else l=mid+1;
117     }
118     l=p+1,r=n-1,R=p;
119     while (l<=r)
120     {
121         int mid=(l+r)>>1,lcp=Query(p+1,mid);
122         if (lcp>=lim) R=mid, l=mid+1;
123         else r=mid-1;
124     }
125     return Query(Root[L],Root[R+1],0,n,R+1,n)>=k;
126 }
127
128 int main()
129 {
130     scanf("%d%d",&c,&k);
131     for (int i=1; i<=c; ++i)
132     {
133         scanf("%s",s);
134         for (int j=0,l=strlen(s); j<l; ++j)
135             ID[n]=i, r[n++]=s[j];
136         End[i]=n; ID[n]=i, r[n++]='#';
137     }
138     Build_SA(); Build_Height();
139     Build_ST(); Build_CT();
140     for (int i=0; i<n; ++i)
141     {
142         if (r[SA[i]]=='#') continue;
143         int l=1,r=End[ID[SA[i]]]-SA[i],ans=0;
144         while (l<=r)
145         {
146             int mid=(l+r)>>1;
147             if (check(i,mid)) ans=mid, l=mid+1;
148             else r=mid-1;
149         }
150         Ans[ID[SA[i]]]+=ans;
151     }
152     for (int i=1; i<=c; ++i)
153         printf("%lld ",Ans[i]);
154 }

转载于:https://www.cnblogs.com/refun/p/10410968.html

BZOJ3473:字符串(后缀数组,主席树,二分,ST表)相关推荐

  1. [HEOI2016/TJOI2016]字符串 (后缀数组+主席树+二分)

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

  2. HDU - 6704 K-th occurrence (后缀数组+主席树)

    题目链接 题意 QQQ次询问,每次询问求SSS的子串出现KKK次的位置 思路 刚开始想的是AC自动机,但是建自动机会超时,后来学长想到后缀数组+主席树的做法Orz...Orz...Orz... 出现K ...

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

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

  4. 洛谷P4094 [HEOI2016/TJOI2016]字符串【后缀数组+主席树+st表】

    时空限制 2000ms / 256MB 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确 ...

  5. HDU4417 Super Mario(离线树状数组或者主席树+二分)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  6. HDU 6194 String String String (后缀数组+线段树, 2017 ACM/ICPC Asia Regional Shenyang Online)

    Problem 求字符串 S 中严格出现 k 次的子串个数 k≥1k\ge 1 |S|≤105|S|\le 10^5 ∑|S|≤2×106\sum |S| \le 2\times 10^6 Idea ...

  7. 线。段。树--树状数组-主席树

    简单了解一下线段树 以前写过的内容,搬运过来 线段树的应用场景:满足区间加法性质且多次查询,什么是区间加法性质,比如最大值,求和,树状数组.线段树.主席树依次. 线段树框架:建树--查询--更新... ...

  8. COGS-257-动态排名系统-树状数组+主席树

    描述 给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作: 1.查询A[i],A[i+1],A[i+2],...,A[j](1<=i< ...

  9. 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树

    题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见-- 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成 ...

最新文章

  1. MIT+IBM同时利用AI探索神经科学,让脑科学研究如虎添翼
  2. mysql多图怎么同时上传,小程序如何同时上传多张图片?
  3. Python 代码混淆和加密技术
  4. 用nginx TCP反向代理作mail邮件代理
  5. python爬取新闻网站标题_python如何正确抓取网页标题
  6. express html文件接收路由参数,express 获取post 请求参数
  7. 为Java应用程序提供了空前的代码保护控件DashO-Pro
  8. HTML基础知识回顾整理
  9. Servlet 身份验证体系结构(源码)
  10. linux 8t的硬盘格式化,linux 新添加的硬盘格式化并挂载到目录下
  11. Sugar BI数据可视化图表标注
  12. 通过调用rundll32.exe来打开一些系统特定文件
  13. Intel Edison 基础开发之配置第一个小程序
  14. 支付宝余额提现收手续费了
  15. 你知道路由器,但是你知道交换机吗?
  16. JAVA原生图片处理:Graphics2D海报升级(二)
  17. CAD创建块后图形依然保持原状?AUTOCAD——特殊字符如何输入
  18. 新版DedeCMS采集发布插件教程工具
  19. 存储程序的概念将计算机转换为,2015计算机二级office高级应用模拟题及答案(1)...
  20. 动态网站开发课后笔记03:Java Web概述

热门文章

  1. 【ES6】JS第7种数据类型:Symbol
  2. MariaDB/MySQL 报错解决:ERROR 1698 (28000): Access denied for user 'root'@'localhost'
  3. mxnet报错解决:AttributeError: module 'mxnet.context' has no attribute 'num_gpus'
  4. Matlab程序咨询,书上程序4-5问题咨询
  5. el图片滚动_element的el-table中记录滚动条位置的示例代码
  6. 中北大学c语言程序设计作业答案,2016年中北大学软件学院程序设计基础考研复试题库...
  7. php中短信验证大致流程,实现php手机短信验证功能的基本思路
  8. SpringBoot自定义请求参数转换器
  9. Specification使用notin
  10. nginx添加stream模块1.20