Brief Description

给定n个字符串,对于每个字符串,您需要求出在所有字符串中出现次数大于等于k次的子串个数。

Algorithm Design

先建立一个广义后缀自动机,什么是广义后缀自动机?就是所有主串一起建立的一个后缀自动机。

广义后缀自动机的建立很简单,对于每个串,该怎么增量建立自动机就怎么建立,只不过为每个节点维护一个set保存这个节点的状态在那些字符串中出现过。当一个串增量构建完毕后,将后缀自动机的last指针指向后缀自动机的根即可进行下一发字符串的增量构建,这样就建出来了一发广义后缀自动机。

考虑一个节点,如果他在x个字符串中出现过,那么他的fa指针所指向的节点所代表的状态出现过的次数一定不小于他。

并且我们已经为每个节点维护了一个set来记录在那些字符串中出现过,那么我们只需要自下向上合并set集合即可,在这之前需要整理出parent树的具体形态,然后一遍dfs,逆序处理set的启发式合并即可。

统计答案只需把每个字符串在自动机上跑,跑到一个节点发现出现次数<K就往fa指针那里跳,直到符合条件。这时候贡献的答案就是当前节点的len属性的值了.

Code

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <set>
#include <string>
const int maxn = 200010;
using std::set;
using std::string;
#define ll long long
set<int> d[maxn];
set<int>::iterator it;
int n, K, tot = 1, head[maxn], sum[maxn];
struct edge {
int to, next;
} e[maxn * 6];
string str[maxn];
struct Suffix_Automaton {
int trans[maxn][26], len[maxn], sz;
int fa[maxn], last, root;
void init() {
tot = 0;
last = root = ++sz;
}
void add(int c, int id) {
int p = last, np = last = ++sz;
len[np] = len[p] + 1;
d[np].insert(id);
while (p && !trans[p][c])
trans[p][c] = np, p = fa[p];
if (!p)
fa[np] = root;
else {
int q = trans[p][c];
if (len[q] == len[p] + 1)
fa[np] = q;
else {
int nq = ++sz;
len[nq] = len[p] + 1;
fa[nq] = fa[q];
for (int i = 0; i < 26; i++)
trans[nq][i] = trans[q][i];
fa[q] = fa[np] = nq;
while (trans[p][c] == q)
trans[p][c] = nq, p = fa[p];
}
}
}
void print() {
for (int i = 1; i <= sz; i++) {
std::cout << fa[i] << ' ';
}
std::cout << std::endl;
for (int i = 1; i <= sz; i++)
printf("%d ", sum[i]);
printf("\n");
}
} sam;
void dfs(int x) {
for (int i = head[x]; i; i = e[i].next) {
int v = e[i].to;
dfs(v);
for (it = d[v].begin(); it != d[v].end(); it++)
d[x].insert(*it);
}
sum[x] = d[x].size();
}
void add_edge(int from, int to) {
e[++tot].to = to;
e[tot].next = head[from];
head[from] = tot;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
scanf("%d %d", &n, &K);
sam.init();
for (int i = 1; i <= n; i++) {
std::cin >> str[i];
int len = str[i].length();
for (int j = 0; j < len; j++)
sam.add(str[i][j] - 'a', i);
sam.last = sam.root;
}
for (int i = 1; i <= sam.sz; i++)
if (sam.fa[i])
add_edge(sam.fa[i], i);
dfs(sam.root);
// sam.print();
if (K > n) {
for (int i = 1; i <= n; i++)
printf("0 ");
return 0;
}
for (int i = 1; i <= n; i++) {
ll ans = 0;
int now = sam.root, len = str[i].length();
for (int j = 0; j < len; j++) {
now = sam.trans[now][str[i][j] - 'a'];
while (sum[now] < K)
now = sam.fa[now];
ans += sam.len[now];
}
printf("%lld ", ans);
}
return 0;
}

[bzoj3277==bzoj3473]出现k次子串计数——广义后缀自动机+STL的更多相关文章

  1. CodeForces-204E:Little Elephant and Strings (广义后缀自动机求出现次数)

    The Little Elephant loves strings very much. He has an array a from n strings, consisting of lowerca ...

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

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

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

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

  4. BZOJ3277: 串(广义后缀自动机)

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1196  Solved: 478[Submit][Status][Discuss] Descripti ...

  5. BZOJ3473 字符串 【广义后缀自动机】

    题目 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? 输入格式 第一行两个整数n,k. 接下来n行每行一个字符串. 输出格式 一行n个整数,第i个整数表 ...

  6. JDOJ 2939: Suffix Automaton 广义后缀自动机_统计子串

    建立广义后缀自动机,对每个节点都建立各自的 $Parent$ 数组. 这样方便统计,不会出现统计错误. 考虑新加入一个字符. 1 这条转移边已经存在,显然对答案没有贡献. 2 这条转移边不存在,贡献即 ...

  7. 后缀自动机(SAM)+广义后缀自动机(GSA)

    经过一顿操作之后竟然疑似没退役0 0 你是XCPC选手吗?我觉得我是! 稍微补一点之前丢给队友的知识吧,除了数论以外都可以看看,为Dhaka和新队伍做点准备... 不错的零基础教程见 IO WIKI ...

  8. bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 对[广义后缀自动机]的一些理解

    先说一下对后缀自动机的理解,主要是对构造过程的理解. 构造中,我们已经得到了前L个字符的后缀自动机,现在我们要得到L+1个字符的后缀自动机,什么需要改变呢? 首先,子串$[0,L+1)$对应的状态不存 ...

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

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

随机推荐

  1. exchange 2007迁移到2010

    标签:exchange 2007 2010 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zpf666.blog.51cto.c ...

  2. Android当代码方法超过65536个时,在2.3机器上会不能安装,出现INSTALL_FAILED_DEXOPT错误

    今天打包时,发现2.3机器,产生的APK在某些机器上不能安装(Installation error: INSTALL_FAILED_DEXOPT),针对这个问题的一个可能解释是:最新的ADT和SDK ...

  3. No resources found. Error from server (NotAcceptable): unknown (get pods)

    问题:正确安装kubectl后,可查询到当前使用集群服务,也可切换不同的集群,但无法获取当前运行的pods的信息与所有的service,具体表现为 $ kubectl get po -nwx No r ...

  4. 利用devcon工具编写bat脚本一键控制系统设备,如开启关闭网卡

    系统WIN7 x64位 下载devcon命令行工具 Download the "Windows Driver Kit (WDK) 7.1.0 from Microsoft: http://w ...

  5. LLLYYY的数字思维(模拟题)

    链接:https://ac.nowcoder.com/acm/contest/318/G LLLYYY很喜欢写暴力模拟贪心思维.某一天在机房,他突然抛给了队友ppq一 个问题.问题如下: 有一个函数f ...

  6. Python音频处理(一)音频基础知识-周振洋

    1.声音音频基础知识 (1)声音是由震动产生,表现为波的形式.波有频率,振幅等参数.对于声波而言:频率越大,音调越高,反之越低.振幅越大,声音越大,反之越小. (2)采样率,帧率:波是连续(无穷)的, ...

  7. ardupilot_gazebo仿真(二)

    ardupilot_gazebo仿真(二) 标签(空格分隔): 未分类 在模型中添加sensor gezebo官网-sensor部分教程 gezebo官网-基础部分教程 Gazebo plugins ...

  8. python 面试题: 列表表达式

    [process() for item1 in iterable1 if condition1 for item2 in iterable2 if condition2 For item3 in it ...

  9. Week2 Teamework from Z.XML 软件分析与用户需求调查(四)Bing桌面及助手的现状与发展

    一.Bing搜索的相关背景 第一,必应搜索前几年的发展重点在于欧美市场,并且取得了一定的成效:根据 Hitwise 的统计数据,Bing 在 2011年3 月份市场占有率突破了 30% 大关,达到 3 ...

  10. beta版本冲刺三

    目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示 ...