Description

字符串是oi界常考的问题。现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中

至少k个字符串的子串(注意包括本身)

Input

第一行两个整数n,k。

接下来n行每行一个字符串。

n,k,l<=100000

Output

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

Sample Input

3 1

abc

a

ab

Sample Output

6 1 3


题解

多个字符串,考虑建广义后缀自动机。

对于每个节点,记录它在每个字符串出现的次数。

但是为了防止重复记录(一个字符串在他的SAM上可能多次匹配到同一个点),我们对每个节点记录一个“上一次统计到的是哪个字符串”,这样子进行有序增加。

当这个字符串跑到某一个节点时,我们把从这个节点,沿着parent树直到根部全部增加。因为一个串在匹配的时候,有可能绕过了他的parent直接匹配到该节点。

然后,对于每一个串,再跑一边。当他的右端点匹配到某个状态以后,立即进行“清算”,把它能够匹配的后缀全部统计。即:沿着Parent树全部加入答案。

但是这样是n^2的,我们预处理前缀和可以做到O(n)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
typedef long long ll;
const int maxn = 2e5+20;
ll ans=0;
int tmp[maxn];
int par[maxn],mx[maxn],tr[maxn][26];
char A[maxn>>1];
int f[maxn];
int cnt = 1,last = 1,Right[maxn];
int c[maxn],id[maxn];
int pre[maxn];
std::string S[maxn];
int n,k;
void extend(int x) {
int p = last;
if(tr[p][x]&&mx[tr[p][x]]==mx[p]+1) {last=tr[p][x];return;}
int np=++cnt;
mx[np]=mx[p]+1;
while(p&&!tr[p][x]) tr[p][x]=np,p=par[p];
if(!p) par[np]=1;
else {
int q = tr[p][x];
if(mx[q]==mx[p]+1) par[np]=q;
else {
int nq = ++cnt;
mx[nq]=mx[p]+1;
memcpy(tr[nq],tr[q],sizeof tr[q]);
par[nq]=par[q];
par[q]=par[np]=nq;
while(p&&tr[p][x]==q) tr[p][x]=nq,p=par[p];
}
}
last = np;
return;
}
inline void topsort() {
for(int i = 1;i<=cnt;++i) ++c[mx[i]];
for(int i = 1;i<=cnt;++i) c[i]+=c[i-1];
for(int i = 1;i<=cnt;++i) id[c[mx[i]]--]=i;
return;
} int main() {
scanf("%d%d",&n,&k);
for(int i = 1;i<=n;++i) {
scanf("%s",A);
S[i]=std::string(A);
int len = S[i].length();
last = 1;
for(int j = 0;j<len;++j) extend(S[i][j]-'a');
}
for(int i = 1;i<=n;++i) {
int len = S[i].length();
int cur = 1;
for(int j = 0;j<len;++j) {
int c = S[i][j]-'a';
while(cur&&!tr[cur][c]) cur=par[cur];
if(!cur) cur=1;
else cur = tr[cur][c];
int tmp = cur;
if(tmp&&pre[tmp]!=i) pre[tmp]=i,++Right[tmp],tmp=par[tmp];
}
}
topsort();
//Right[1]=0;
for(int i = 1;i<=cnt;++i) f[id[i]]=f[par[id[i]]]+(Right[id[i]]>=k?mx[id[i]]-mx[par[id[i]]]:0);
for(int i = 1;i<=n;++i) {
int len = S[i].length();
int cur=1,L=0;
ll ans = 0;
for(int j = 0;j<len;++j) {
int c = S[i][j]-'a';
while(cur&&!tr[cur][c]) cur=par[cur];
if(!cur) cur=1,L=0;
else L=std::min(L,mx[cur])+1,cur = tr[cur][c];
if(L==mx[cur]||Right[cur]<k)
ans+=f[cur];
else {
ans+=f[cur];
ans-=mx[cur];
ans+=L;
}
}
printf("%lld ",ans);
}
return 0;
}

【文文殿下】[BZOJ3277] 串的更多相关文章

  1. BZOJ3473&&BZOJ3277串

    BZOJ3473&&BZOJ3277串 题面 自己找去 HINT 对于所有串建立一个广义后缀自动机,对于每一个节点开一个set表示这个节点接受的子串在哪些串里出现过,然后在parent ...

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

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

  3. BZOJ3277——串

    0.题意:给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 1.分析:这个题我问了吴大爷做法 首先建立后缀自动机,然后利用离线搞出每一个 ...

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

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

  5. 【文文殿下】WC2019游记

    Day0 今天早上三点半才睡着,五点起床,前往省城郑州.与省实验常老师汇合,坐上高铁,下午三点半多才到广州二中. 下午随便找了一个教室进去敲一敲代码,发现自己越来越菜了. 和一大堆网上的dalao面基 ...

  6. 【文文殿下】NOIp2018游记

    Day-1 本段更新于 2018年11月8日23:26:44 今天还在机房里面,无所事事吧.上午睡了一上午,出去理了一下发,花了20块钱 QAQ. 下午来到机房,复习了一下exgcd的东西. 发现自己 ...

  7. 【文文殿下】【CF724C】Ray Tracing (中国剩余定理)

    题解 我们考虑将棋盘扩大一倍,这样相当于取膜.然后,我们只要对x,y,的位置分类讨论,做四次crt就行.具体细节看文文代码. #include<cstdio> #include<al ...

  8. bzoj3473: 字符串 && bzoj3277串

    3473: 字符串 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 121  Solved: 53[Submit][Status][Discuss] D ...

  9. 【文文殿下】后缀自动机(Suffix Automaton,SAM)学习笔记

    前言 后缀自动机是一个强大的数据结构,能够解决很多字符串相关的(String-related)问题. 例如:他可以查询一个字符串在另一个字符串中出现的所有子串,以及查询一个字符串中本质不同的字符串的个 ...

随机推荐

  1. Android工程目录结构

    ----------siwuxie095 首先创建一个简单的项目:MainActivity 工程目录结构一览: 工程目录结构介绍: 1.manifests目录 里面有一个AndroidManifest ...

  2. MongoDB 自动分片 auto sharding

    MongoDB部署实验系列文章 MongoDB做为NoSQL数据库,最近几年持续升温,越来越多的企业都开始尝试用MongoDB代替原有Database做一些事情.MongoDB也在集群,分片,复制上也 ...

  3. Flannel网络部署

    一.Flannel网络部署 为Flannel生成证书 [root@linux-node1 ssl]# vim flanneld-csr.json { "CN": "fla ...

  4. How To Debug Qmake Pro File

    对于程序代码,我们经常使用到调试. 可是,对于有些项目的配置文件,比如Qt的Pro文件, 一个项目复杂的话,Pro文件就很容易出错. 此时的Pro文件,如果也能调试的话,那么是十分的快捷方便的. 解决 ...

  5. Criterion - 一个简单可扩展的 C 语言测试框架

    A dead-simple, yet extensible, C test framework. Philosophy Most test frameworks for C require a lot ...

  6. using namespace cv

    在OpenCV中使用 using namespace cv 的作用: 在使用#include语句包含相应头文件后,使用下面语句即可包含相应的Opencv命名空间 using namespace cv; ...

  7. Laravel 上传文件处理

    文件上传 获取上传的文件 可以使用 Illuminate\Http\Request 实例提供的 file 方法或者动态属性来访问上传文件, file 方法返回 Illuminate\Http\Uplo ...

  8. 为什么都说UX / UI设计师是最佳工作?

    以下内容由Mockplus团队翻译整理,仅供学习交流,Mockplus是更快更简单的原型设计工具. 你将成为永远热爱自己工作的人,做着自己喜欢的工作还能得到相应的成果和报酬,就好似在度带薪年假一般,何 ...

  9. qt学习(二) buttong layout spinbox slider 示例

    开启qt5 creator 新建项目 qt widgets 改写main.cpp #include "mainwindow.h" #include <QApplication ...

  10. tera term通过ttl脚本 自动连接服务器

    在现在的这个公司一直使用tera term来远程连接服务器,感觉很方便,特别是它的ttl脚本配置的自动连接.有时候我们可能无法直接连接到目标服务器,需要通过ssh经过多个中间服务器才能连接到目标服务器 ...