BZOJ3277: 串(广义后缀自动机)
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1196 Solved: 478
[Submit][Status][Discuss]
Description
Input
Output
输出一行n个整数,第i个整数表示第i个字符串的答案。
Sample Input
abc
a
ab
Sample Output
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: 串(广义后缀自动机)的更多相关文章
- BZOJ 3277 串 (广义后缀自动机)
3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] De ...
- BZOJ3277: 串(后缀自动机,Parent树,Dfs序)
Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中 至少k个字符串的子串(注意包括本身). Input 第一行两个整数n, ...
- BZOJ3277 串(后缀自动机)
对多串建立SAM的一种方法是加分隔符.于是加完分隔符建出SAM. 考虑统计出每个节点被多少个串包含.让每个串各自在SAM上跑,跑到一个节点就标记(显然一定会完全匹配该节点,因为是对包含其的串建的SAM ...
- 2018.12.22 bzoj3277: 串(后缀自动机+启发式合并)
传送门 跟这道题是一模一样的. 于是本蒟蒻又写了一遍10min1A庆祝 代码: #include<bits/stdc++.h> #define ri register int using ...
- BZOJ3277 串 【广义后缀自动机】
Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中 至少k个字符串的子串(注意包括本身). Input 第一行两个整数n, ...
- 【bzoj3277/bzoj3473】串/字符串 广义后缀自动机
题目描述 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 输入 第一行两个整数n,k.接下来n行每行一个 ...
- 【BZOJ3277】串(后缀自动机)
[BZOJ3277]串(后缀自动机) 题面 BZOJ 题解 广义后缀自动机??? 照着别人的打了一遍.. 相当于每个串都构建一个后缀自动机 构建完一个串之后,直接把当前的last指回root就行了?? ...
- 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 ...
- 【BZOJ3227】串【广义后缀自动机】
题意 给出n个字符串,问每个字符串中有多少子串是这所有的n个字符串中至少k个的子串. 分析 广义后缀自动机模板题.对这n个串建广义后缀自动机,对于每个状态维护两个值cou[u]和lcu[u]分别代表拥 ...
随机推荐
- Java ScheduledExecutorService源码分析
Java 定时任务可以用Timer + TimerTask来做,或者使用ScheduledExecutorService,使用ScheduledExecutorService有两个好处: 1. 如果任 ...
- Spring课程 Spring入门篇 5-2 配置切面aspect
本节主要讲了在xml中配置切面的demo 1 解析 1.1 配置切面xml 1.2 配置切面xml 1.3 问:什么是动态代理? 2 代码演练 2.1 配置切面xml 1 解析 1.1 配置切面xml ...
- 【代码笔记】JTable 、TableModel的使用3
在java中插入Table,并通过TableModel插入表格初始化状态后,如果需要第一行标题栏进行重命名,直接利用TableModel接口去实现列名修改,在图形显示中是无法实现的. 这里需要用到 J ...
- 采用C/C++语言如何实现复数抽象数据类型Complex
记录一下! 采用C/C++语言如何实现复数抽象数据类型Complex #include <stdio.h> typedef struct Complex { double e1; // 实 ...
- OPENCV VS设置
OPENCV VS设置 第一步 工程->工具->选项->VC++目录 第二步 这两项放到系统path下 D:\OpenCV2.4.3\VS\bin\Debug;D:\OpenCV2. ...
- 统计学中的P值与显著性的意义
统计学意义(p值) 结果的统计学意义是结果真实程度(能够代表总体)的一种估计方法.专业上,p值为结果可信程度的一个递减指标,p值越大,我们越不能认为样本中变量的关联是总体中各变量关联的可靠指标.p值是 ...
- windows下使用xerces -c解析XML
windows下使用Xerces-C++解析XML 前景提要 最近工作中遇到收到的数据为xml格式的情况,考虑到xml解析应该是个很常用的功能,应该有开源的lib库可以使用,于是就在网上找了找,果然发 ...
- matlab练习程序(Ritter‘s最小包围圆)
原始算法是sphere,我这里简化为circle了. Ritter's求最小包围圆为线性算法,因为非常简单,所以应用非常广泛. 该算法求出的圆比最优圆大概会大个5%到20%左右,求最优圆应该可以用Bo ...
- mongodb 3.4 学习 (二)命令
# 使用或切换数据库 use <database name> # 显示所有数据库 show dbs # 显示所有collection show collections # 显示所有user ...
- C#并行编程 z
目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C#并行编程-线程同步原语 C#并行编程-PLINQ:声明式数据并行 背景 基于任务的程序 ...