BZOJ 3473: 字符串 (广义后缀自动机)
/*
广义后缀自动机, 每次加入维护 该right集合的set, 然后可以更新所有的parent,最终能够出现在k个串中right集合也就是set大小大于等于k的部分
这样的话就给了我们要跳的节点加了一个限制, 也就是跳的时候调到第一个sz>= k的节点, 因为更长的话答案不会增加
数据范围非常迷
好吧 暴力合并set复杂度过高
暴力更新祖先的情况竟然会少一个log
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<set>
#include<string>
#include<iostream>
#define ll long long
#define mmp make_pair
#define M 400020
using namespace std;
int read()
{
int nm = 0, f = 1;
char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
return nm * f;
}
int lst = 1, cnt = 1, fa[M], len[M], ch[M][26], tim[M], a[M], n, k;
ll f[M], cor[M], g[M];
//set<int> st[M];
string s[M];
//vector<int> to[M];
void insert(int c)
{
int p = ++cnt, f = lst;
lst = p;
len[p] = len[f] + 1;
while(f && !ch[f][c]) ch[f][c] = p, f = fa[f];
if(!f) fa[p] = 1;
else
{
int q = ch[f][c];
if(len[q] == len[f] + 1) fa[p] = q;
else
{
int nq = ++cnt;
memcpy(ch[nq], ch[q], sizeof(ch[nq]));
fa[nq] = fa[q];
len[nq] = len[f] + 1;
fa[p] = fa[q] = nq;
while(f && ch[f][c] == q) ch[f][c] = nq, f = fa[f];
}
}
}
//void dfs(int now)
//{
// for(int i = 0; i < to[now].size(); i++)
// {
// int vj = to[now][i];
// dfs(vj);
// for(set<int>::iterator it = st[vj].begin(); it != st[vj].end(); it++)
// {
// st[now].insert(*it);
// }
// }
// f[now] = st[now].size();
//}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> k;
for(int i = 1; i <= n; i++)
{
cin >> s[i];
lst = 1;
int l = s[i].length();
for(int j = 0; j < l; j++)
{
insert(s[i][j] - 'a');
}
}
for(int i = 1; i <= n; i++)
{
int now = 1;
for(int j = 0; j < s[i].length(); j++)
{
int c = s[i][j] - 'a';
now = ch[now][c];
int p = now;
for(; p && cor[p] != i; p = fa[p]) g[p]++, cor[p] = i;
}
}
for(int i = 1; i <= cnt; i++) tim[len[i]]++;
for(int i = 1; i <= cnt; i++) tim[i] += tim[i - 1];
for(int i = 1; i <= cnt; i++) a[tim[len[i]]--] = i;
// for(int i = cnt; i >= 1; i--)
// {
// f[a[i]] = st[a[i]].size();
// for(set<int>::iterator it = st[a[i]].begin(); it != st[a[i]].end(); ++it)
// {
// st[fa[a[i]]].insert(*it);
// }
// }
// for(int i = 2; i <= cnt; i++) to[fa[i]].push_back(i);
// dfs(1);
g[1] = 0;
for(int i = 1; i <= cnt; i++)
{
int now = a[i];
f[now] = f[fa[now]];
if(g[now] >= k) f[now] += len[now] - len[fa[now]];
}
if(k > n)
{
for(int i = 1; i <= n; i++) cout << "0 ";
}
else
{
ll ans;
for(int i = 1; i <= n; i++)
{
ans = 0;
int now = 1, l = s[i].length();
for(int j = 0; j < l; j++)
{
int c = s[i][j] - 'a';
now = ch[now][c];
ans += f[now];
}
cout << ans << " ";
}
}
return 0;
}
/*
3 3
abcdfdsadaseeeeeeeeefffffffffffffffffffffffffffffffffffffffffffeeeeeeee
affsfdsdfewfeeeeeeffffffffeeeeeeeee
abasdsadwdsadsadwdasdadafsafs
*/
BZOJ 3473: 字符串 (广义后缀自动机)的更多相关文章
- 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) ...
- BZOJ 3473 字符串 ——广义后缀自动机
这题就比较有趣了. 首先匹配一遍,然后统计子树叶子节点中包含大于等于k的节点个数(HH的项链) 然后就可以搞了. 关于合法的情况数,显然是l[i]-l[fa[i]],然后向下下传即可(YY一下). # ...
- bzoj 3277: 串 & bzoj 3473: 字符串【后缀自动机||后缀数组】
建一个广义后缀自动机(每加完一个串都返回root),在parent树上dpsum记录合法长度,打着时间戳往上跳,最后每个串在自动机上跑一变统计答案即可. 后缀数组理解起来可能方便一点,但是难写,就只说 ...
- BZOJ 3277 串 (广义后缀自动机)
3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] De ...
- 【bzoj3277/bzoj3473】串/字符串 广义后缀自动机
题目描述 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 输入 第一行两个整数n,k.接下来n行每行一个 ...
- BZOJ 2894: 世界线 广义后缀自动机
Code: #include<bits/stdc++.h> #define maxn 300000 #define ll long long using namespace std; ve ...
- bzoj 3926 转换+广义后缀自动机
思路:重点在于叶子节点只有20个,我们把叶子节点提到根,把20个trie图插入后缀自动机,然后就是算有多少个本质不同的字串. #include<bits/stdc++.h> #define ...
- BZOJ 4180: 字符串计数 后缀自动机 + 矩阵乘法 + 二分(神题)
Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999. 他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C ...
- BZOJ3473 字符串 广义后缀自动机
今天主攻了下SAM 好多东西以前都没理解到 对于这道题 我们建一个自动机存所有串 每个穿last从1开始 对于自动机上每个点额外记一个cnt 表示能匹配到这个点的不同串个数 建完对每个串在自动机上匹配 ...
随机推荐
- JDK动态代理实例
最近看<深入浅出MyBatis技术原理与实战>这本书时,里面讲到Mapper接口的内部实现是通过JDK动态代理生成实现类,联想到之前看<SPRING技术内幕>这本书里也常常提到 ...
- 怎么在vi和vim上查找字符串
教你怎么在vi和vim上查找字符串 我们以samba的配置文件为例,搜索一个user的字符串. vim /etc/samba/smb.conf 打开smb.conf 命令模式下,输入/use ...
- 使用.pth文件扩展python环境路径
使用.pth文件扩展python环境路径 有时候我们不希望把一个库放到 site-packages 下面,而是更愿意把它保留在原始的工程目录中,方便管理和维护.那么怎么能让 Python 运行环境找到 ...
- 查看Linux系统版本信息(转)
一.查看Linux内核版本命令(两种方法): 1.cat /proc/version [root@S-CentOS home]# cat /proc/version Linux version 2.6 ...
- ps 和 top 的cpu的区别
cpu的计算 ps cpu的定义 man page中给出的定义: cpu utilization of the process in "##.#" format. Currentl ...
- RedHat7.3安装MySQL5.7
1.下载Mysql安装包 https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.20-1.el6.x86_64.rpm-bundle.tar 附百度 ...
- 自动加载以及Composer的实现
类的自动加载 两个函数 __autoload()魔术方法.spl_autoload_register 当php文件中使用了new关键字实例化一个对象时,如果该类没有在本php文件中被定义,将会触发__ ...
- 关于java的一些小知识(课程作业01)
1,在java源代码中加空格注释不会影响程序的编译速度. 2,一个java类文件中真的只能有一个公有类吗? 如果只在第一个public类里面定义实体,或者两个都不定义并没有报错且程序可以运行.每个编译 ...
- JavaScript之WebSocket技术详解
概述 HTTP协议是一种无状态协议,服务器端本身不具有识别客户端的能力,必须借助外部机制,比如session和cookie,才能与特定客户端保持对话.这多多少少带来一些不便,尤其在服务器端与客户端需要 ...
- 利用VMware虚拟机安装CentOS7
CentOS7镜像下载:http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-1804.iso VMware虚拟 ...