Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1196  Solved: 478
[Submit][Status][Discuss]

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

HINT

Source

广义后缀自动机?就是把一坨字符串建到一个后缀自动机上??

不过好难理解啊qwq。。

对于这题,首先我们要知道几个定理

1.节点$i$表示的本质不同的字符串可以由$len[i] - len[fa[i]]$得到

2.一个串的子串 等价于 一个串所有前缀的所有后缀

这样子串就转换为求一个串的前缀的所有后缀的问题

前缀可以枚举,问题转换为求一个字符串的各个后缀在其他字符串中出现了多少次

这样我们可以把广义后缀自动机建出来,然后暴力沿着$parent$边跑,这样可以枚举出所有后缀

同时为了不重复枚举,我们需要记录下每个后缀是否已经被枚举过了

这样我们就可以知道一个状态出现的次数是否$>= K$,接下来我们只要统计出这个状态出现的次数就行了

根据定理$1$,这个很好统计

然后就做完啦

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1e6 + ;
string s[MAXN];
int N, K;
int fa[MAXN], len[MAXN], ch[MAXN][], root = , last = , tot = , times[MAXN];
void insert(int x) {
int now = ++tot, pre = last; last = now; len[now] = len[pre] + ;
for(; pre && !ch[pre][x]; pre = fa[pre]) ch[pre][x] = now;
if(!pre) fa[now] = root;
else {
int q = ch[pre][x];
if(len[q] == len[pre] + ) fa[now] = q;
else {
int nows = ++tot; len[nows] = len[pre] + ;
memcpy(ch[nows], ch[q], sizeof(ch[q]));
fa[nows] = fa[q]; fa[q] = fa[now] = nows;
for(; pre && ch[pre][x] == q; pre = fa[pre]) ch[pre][x] = nows;
}
}
}
int vis[MAXN], sum[MAXN];
void GetTimes() {//求出每一个状态在几个字符串出现过
for(int i = ; i <= N; i++) {
int now = root;
for(int j = ; j < s[i].length(); j++) {
now = ch[now][s[i][j] - 'a'];//枚举每一个前缀
int t = now;
while(t && vis[t] != i) vis[t] = i, times[t]++, t = fa[t];//枚举每一个后缀
}
}
}
void dfs(int x) {
if(x == root || vis[x]) return ;
vis[x] = ;
dfs(fa[x]);
sum[x] += sum[fa[x]];
}
int main() {
#ifdef WIN32
freopen("a.in", "r", stdin);
#endif
ios::sync_with_stdio();
cin >> N >> K;
for(int i = ; i <= N; i++) cin >> s[i];
for(int i = ; i <= N; i++) {
last = ;
for(int j = ; j < s[i].length(); j++)
insert(s[i][j] - 'a');
} GetTimes(); for(int i = ; i <= tot; i++) sum[i] = (times[i] >= K) * (len[i] - len[fa[i]]);//i状态所表示的子串集合对答案的贡献
memset(vis, , sizeof(vis));
for(int i = ; i <= tot; i++) dfs(i);
for(int i = ; i <= N; i++) {
int ans = , now = root;
for(int j = ; j < s[i].length(); j++)
now = ch[now][s[i][j] - 'a'], ans += sum[now];
//枚举前缀,算出每一个前缀所包含的后缀对答案啊的贡献
printf("%d ", ans);
} return ;
}

 

BZOJ3277: 串(广义后缀自动机)的更多相关文章

  1. BZOJ 3277 串 (广义后缀自动机)

    3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] De ...

  2. BZOJ3277: 串(后缀自动机,Parent树,Dfs序)

    Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中 至少k个字符串的子串(注意包括本身). Input 第一行两个整数n, ...

  3. BZOJ3277 串(后缀自动机)

    对多串建立SAM的一种方法是加分隔符.于是加完分隔符建出SAM. 考虑统计出每个节点被多少个串包含.让每个串各自在SAM上跑,跑到一个节点就标记(显然一定会完全匹配该节点,因为是对包含其的串建的SAM ...

  4. 2018.12.22 bzoj3277: 串(后缀自动机+启发式合并)

    传送门 跟这道题是一模一样的. 于是本蒟蒻又写了一遍10min1A庆祝 代码: #include<bits/stdc++.h> #define ri register int using ...

  5. BZOJ3277 串 【广义后缀自动机】

    Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中 至少k个字符串的子串(注意包括本身). Input 第一行两个整数n, ...

  6. 【bzoj3277/bzoj3473】串/字符串 广义后缀自动机

    题目描述 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 输入 第一行两个整数n,k.接下来n行每行一个 ...

  7. 【BZOJ3277】串(后缀自动机)

    [BZOJ3277]串(后缀自动机) 题面 BZOJ 题解 广义后缀自动机??? 照着别人的打了一遍.. 相当于每个串都构建一个后缀自动机 构建完一个串之后,直接把当前的last指回root就行了?? ...

  8. bzoj 3277 串 && bzoj 3473 字符串 && bzoj 2780 [Spoj]8093 Sevenk Love Oimaster——广义后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3277 https://www.lydsy.com/JudgeOnline/problem.p ...

  9. 【BZOJ3227】串【广义后缀自动机】

    题意 给出n个字符串,问每个字符串中有多少子串是这所有的n个字符串中至少k个的子串. 分析 广义后缀自动机模板题.对这n个串建广义后缀自动机,对于每个状态维护两个值cou[u]和lcu[u]分别代表拥 ...

随机推荐

  1. PHP性能检测与优化—XHProf 数据阅读

    PHP性能检测与优化—XHProf 数据阅读 一.      效果如下 请求总揽 函数调用情况 二.      参数含义 Inclusive Time              包括子函数所有执行时间 ...

  2. vue使用qrcode生成二维码,可以自定义大小

    1,qrcanvas-vue插件,https://gera2ld.github.io/qrcanvas-vue/#logo.只支持像素大小的二维码 2,qrcode支持移动端自定义大小二维码 &quo ...

  3. 30 Excellent WordPress Video Tutorials

    http://sixrevisions.com/wordpress/30-excellent-wordpress-video-tutorials/ WordPress是一种使用PHP语言开发的博客平台 ...

  4. Linux漏洞分析入门笔记-CVE_2018_6323_整型溢出

    操作系统   Ubuntu 16.04 /32 位 调试器     IDA pro 7.0 漏洞软件   binutils-2.29.1 0x00: 漏洞描述 1.什么是整数溢出: 在计算机中,整数分 ...

  5. Java web的安全约束--Basic验证

    要进行basic验证是用户名/口令机制,当浏览器要访问受保护的资源时,服务器会要求一个用户名和口令,只有输入了合法的用户名和口令.服务器才发送资源.用户名和口令可以存储在安全域中.安全域是标识一个We ...

  6. linux下使用第三方商店安装应用

    安装 snap store 进行下载,相当与第三方应用商店,但是往往比某一个官方软件源里面的应用要丰富或更实用 到 snap docs 中选择你的 linux 版本进入安装文档,根据指示一步一步安装即 ...

  7. ICONIX Process

    1.像rup,iconix是用例驱动的但是比rup更轻量级.  iconix 仅仅使用四种diagram(用例图.健壮性图.时序图.类图)就可以把用例文本转成代码. 2.值得注意的健壮性分析图并不是u ...

  8. Spring Boot学习路线

    Spring Boot 学习路线,本文计划根据作者近几年的工作.学习经验,来分析和制定一个学习使用 Spring Boot技术的步骤路线图. SpringBoot是伴随着Spring4.0诞生的: S ...

  9. meat标签使用

    meta是html语言head区的一个辅助性标签.几乎所有的网页里,我们可以看到类似下面这段的html代码: <head> <meta http-equiv="conten ...

  10. June 17th 2017 Week 24th Saturday

    Absence sharpens love, presence strengthens it. 相聚爱益切,离别情更深. There is almost no such love that can i ...