【bzoj3277/bzoj3473】串/字符串 广义后缀自动机
题目描述
输入
接下来n行每行一个字符串。
输出
样例输入
3 1
abc
a
ab
样例输出
6 1 3
题解
广义后缀自动机
建立广义后缀自动机,统计一下每个节点属于多少个字符串中。
在每次插入新节点np后,parent树上np的父亲节点fa[np]一定有着np的身份,即一定包含当前串(这里将root节点视作在所有串中)。
那么沿着parent树一直向上更新即可。更新到已经被更新过的节点就停止。
这样时间复杂度是O(n)的。
求出每个节点在几个子串中以后,还要知道出现次数。
而出现次数有一个定理:x结尾的不重复字符串的出现次数=dis[x]-dis[fa[x]]。
简单证明一下:从root走到parent树上x到root的链上的点共有dis[x]种方法,走到fa[x]到root的链上的点共有dis[fa[x]]种方法,相减可推出结论。
而仅仅求出不重复字符串的出现次数还不够,我们需要统计所有的出现位置。而出现位置一定是在parent树中从x到叶子结点均出现的。
那么可以用类似于树形dp的方法求解。
总结一下:建立广义后缀自动机,同时统计每个节点在多少个字符串中出现过。保留出现在≥k个字符串中的,令出现次数为dis[x]-dis[fa[x]]。然后树形dp,c[x]+=c[fa[x]],并更新答案求解。
说了这么多,其实代码也就几十行~
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 200010
using namespace std;
int a[N][26] , fa[N] , kind[N] , type[N] , si[N] , last , tot = 1;
int head[N] , to[N] , next[N] , cnt;
long long dis[N] , c[N] , ans[N];
char str[N];
void add(int x , int y)
{
to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
void ins(int t , int c)
{
int p = last , np = last = ++tot;
dis[np] = dis[p] + 1 , kind[np] = t;
while(p && !a[p][c]) a[p][c] = np , p = fa[p];
if(!p) fa[np] = 1;
else
{
int q = a[p][c];
if(dis[q] == dis[p] + 1) fa[np] = q;
else
{
int nq = ++tot;
memcpy(a[nq] , a[q] , sizeof(a[q])) , dis[nq] = dis[p] + 1 , fa[nq] = fa[q] , fa[np] = fa[q] = nq , si[nq] = si[q] , type[nq] = type[q];
while(p && a[p][c] == q) a[p][c] = nq , p = fa[p];
}
}
for(p = np ; p && type[p] != t ; p = fa[p]) si[p] ++ , type[p] = t;
}
void dfs(int x)
{
int i;
c[x] += c[fa[x]] , ans[kind[x]] += c[x];
for(i = head[x] ; i ; i = next[i])
dfs(to[i]);
}
int main()
{
int n , m , k , i , j;
scanf("%d%d" , &n , &k);
for(i = 1 ; i <= n ; i ++ )
{
scanf("%s" , str + 1) , m = strlen(str + 1) , last = 1;
for(j = 1 ; j <= m ; j ++ ) ins(i , str[j] - 'a');
}
for(i = 2 ; i <= tot ; i ++ )
{
add(fa[i] , i);
if(si[i] >= k) c[i] = dis[i] - dis[fa[i]];
}
dfs(1);
for(i = 1 ; i <= n ; i ++ ) printf("%lld " , ans[i]);
return 0;
}
【bzoj3277/bzoj3473】串/字符串 广义后缀自动机的更多相关文章
- 【BZOJ3227】串【广义后缀自动机】
题意 给出n个字符串,问每个字符串中有多少子串是这所有的n个字符串中至少k个的子串. 分析 广义后缀自动机模板题.对这n个串建广义后缀自动机,对于每个状态维护两个值cou[u]和lcu[u]分别代表拥 ...
- BZOJ3277 串 【广义后缀自动机】
Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中 至少k个字符串的子串(注意包括本身). Input 第一行两个整数n, ...
- BZOJ 3473: 字符串 [广义后缀自动机]
3473: 字符串 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 354 Solved: 160[Submit][Status][Discuss] ...
- BZOJ 3277 串 & BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析、启发式合并、线段树合并、主席树)
标签那么长是因为做法太多了... 题目链接: (bzoj 3277) https://www.lydsy.com/JudgeOnline/problem.php?id=3277 (bzoj 3473) ...
- BZOJ3473 字符串 广义后缀自动机
今天主攻了下SAM 好多东西以前都没理解到 对于这道题 我们建一个自动机存所有串 每个穿last从1开始 对于自动机上每个点额外记一个cnt 表示能匹配到这个点的不同串个数 建完对每个串在自动机上匹配 ...
- BZOJ 3473 字符串 ——广义后缀自动机
这题就比较有趣了. 首先匹配一遍,然后统计子树叶子节点中包含大于等于k的节点个数(HH的项链) 然后就可以搞了. 关于合法的情况数,显然是l[i]-l[fa[i]],然后向下下传即可(YY一下). # ...
- [bzoj2780][Spoj8093]Sevenk Love Oimaster_广义后缀自动机
Sevenk Love Oimaster bzoj-2780 Spoj-8093 题目大意:给定$n$个大串和$m$次询问,每次给出一个字符串$s$询问在多少个大串中出现过. 注释:$1\le n\l ...
- JZOJ5915 [2018NOIP模拟] 明日之星(广义后缀自动机,线段树)
题目描述 给定一棵树,每个节点有一个权值 \(a_i\) 和一个字符串 \(s_i\). q组询问,每次询问一个字符串 S 和两个节点x,y: 求x到y路径上每个节点的字符串在 S 中出现的次数乘上各 ...
- CF 666E Forensic Examination——广义后缀自动机+线段树合并
题目:http://codeforces.com/contest/666/problem/E 对模式串建广义后缀自动机,询问的时候把询问子串对应到广义后缀自动机的节点上,就处理了“区间”询问. 还要处 ...
随机推荐
- Android(java)学习笔记80:Html嵌入到Java显示乱码
1. Html嵌入到Java显示乱码: 解决方案: 使用 loadData方法是中文部分会出现乱码,即使指定“utf-8”.“gbk”.“gb2312”也一样. webView.getSettings ...
- fmt - 简易的文本格式优化工具 simple optimal text formatter
总览 (SYNOPSIS) ../src/fmt [-DIGITS] [OPTION]... [FILE]... 描述 (DESCRIPTION) 重新 格式化 文件 FILE(s) 中的 每一个 段 ...
- CentOS系统下安装Redis
1. 安装C语言环境 yum install gcc-c++ 2.下载Redis安装包 http://download.redis.io/releases/redis-3.2.9.tar.gz 3.解 ...
- java字符格式
http://blog.chinaunix.net/uid-12348673-id-3335300.html http://blog.csdn.net/zhouyong80/article/detai ...
- 微服务SpringCloud+Docker入门到高级实战(教程详情)
第一章 课程介绍和学习路线 1.微服务架构SpringCloud课程介绍 简介:课程介绍和课程大纲讲解,讲课风格和重点内容理解技巧 2.技术选型和学后水平 简介:课程所需基础和技术选型讲解,学完课程可 ...
- 01_13_JSP编译指令
01_13_JSP编译指令 1. Directive Directive(编译指令)相当于在编译期间的命令 格式: <%@Directive 属性=”属性值”%> 常见的Directive ...
- jpeg解码库使用实例
jpeg库下载地址: http://www.ijg.org/ 交叉编译三部曲: A ./configure --host=arm-linux-gcc --prefix=/home/flying/jpe ...
- Linux的链接文件
Linux的链接文件======================================== Linux的链接文件分为硬链接文件(hard link )和软链接文件( symbolic lin ...
- shell数组脚本
#!/bin/bash array=( ) ;i<${#array[*]};i++)) do echo ${array[i]} done 脚本2 #!/bin/bash array=( ) fo ...
- confirm() 方法用于显示一个带有指定消息和 OK 及取消按钮的对话框。系统自带提示
W3C地址::::::: http://www.w3school.com.cn/jsref/met_win_confirm.asp http://www.w3school.com.cn/tiy/t ...