【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 对模式串建广义后缀自动机,询问的时候把询问子串对应到广义后缀自动机的节点上,就处理了“区间”询问. 还要处 ...
随机推荐
- python_27_多级字典嵌套及操作
#key-value 字典无下标 所以乱序,key值尽量不要取中文 person_log={ '大二':{ 'Ya Nan':['free','cute','soso'], 'Sha sha':['微 ...
- 网络流_Edmond-Karp算法、Dinic算法
转载:网络流基础篇——Edmond-Karp算法 BY纳米黑客 网络流的相关定义: 源点:有n个点,有m条有向边,有一个点很特殊,只出不进,叫做源点. 汇点:另一个点也很特殊, ...
- MySQL - 在sql语句执行时是先执行触发器再检查约束条件的
在sql语句执行时是先执行触发器再检查约束条件的
- (SSO)单点登录原理和总结
一:什么是单点登录(single Sign-On) SSO 是一种统一认证和授权机制,指访问统一服务器不用应用中的受保护资源的同一用户,只需要登录一次,即通过一个应用中的安全验证后, 再访问其他应用中 ...
- PHP静态文件缓存
ob_start(); 2 echo 'aaa'; 3 $string = ob_get_contents(); 4 file_put_contents('a.html', $string); 5 o ...
- BootStrap下拉框搜索功能
<!DOCTYPE html> <html> <head> <title>jQuery bootstrap-select可搜索多选下拉列表插件-www. ...
- 24.VUE学习之-变异方法filter与regexp实现评论搜索功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- BFS:HDU2612-Find a way(双向BFS)
Find a way Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- eclipse快捷键(shift+ctrl+l能出来所有的快捷键)
[ALT+/]此快捷键为用户编辑的好帮手,能为用户提供内容的辅助,不要为记不全方法和属性名称犯愁,当记不全类.方法和属性的名字时,多体验一下[ALT+/]快捷键带来的好处吧. 2 [Ctrl+O]显示 ...
- LOJ #6010. 「网络流 24 题」数字梯形
#6010. 「网络流 24 题」数字梯形 题目描述 给定一个由 n nn 行数字组成的数字梯形如下图所示.梯形的第一行有 m mm 个数字.从梯形的顶部的 m mm 个数字开始,在每个数字处可以 ...