/*
广义后缀自动机, 每次加入维护 该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: 字符串 (广义后缀自动机)的更多相关文章

  1. BZOJ 3473: 字符串 [广义后缀自动机]

    3473: 字符串 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 354  Solved: 160[Submit][Status][Discuss] ...

  2. BZOJ 3277 串 & BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析、启发式合并、线段树合并、主席树)

    标签那么长是因为做法太多了... 题目链接: (bzoj 3277) https://www.lydsy.com/JudgeOnline/problem.php?id=3277 (bzoj 3473) ...

  3. BZOJ 3473 字符串 ——广义后缀自动机

    这题就比较有趣了. 首先匹配一遍,然后统计子树叶子节点中包含大于等于k的节点个数(HH的项链) 然后就可以搞了. 关于合法的情况数,显然是l[i]-l[fa[i]],然后向下下传即可(YY一下). # ...

  4. bzoj 3277: 串 & bzoj 3473: 字符串【后缀自动机||后缀数组】

    建一个广义后缀自动机(每加完一个串都返回root),在parent树上dpsum记录合法长度,打着时间戳往上跳,最后每个串在自动机上跑一变统计答案即可. 后缀数组理解起来可能方便一点,但是难写,就只说 ...

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

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

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

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

  7. BZOJ 2894: 世界线 广义后缀自动机

    Code: #include<bits/stdc++.h> #define maxn 300000 #define ll long long using namespace std; ve ...

  8. bzoj 3926 转换+广义后缀自动机

    思路:重点在于叶子节点只有20个,我们把叶子节点提到根,把20个trie图插入后缀自动机,然后就是算有多少个本质不同的字串. #include<bits/stdc++.h> #define ...

  9. BZOJ 4180: 字符串计数 后缀自动机 + 矩阵乘法 + 二分(神题)

    Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999.   他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C ...

  10. BZOJ3473 字符串 广义后缀自动机

    今天主攻了下SAM 好多东西以前都没理解到 对于这道题 我们建一个自动机存所有串 每个穿last从1开始 对于自动机上每个点额外记一个cnt 表示能匹配到这个点的不同串个数 建完对每个串在自动机上匹配 ...

随机推荐

  1. TypeScript 之 tsconfig.json

    https://m.runoob.com/manual/gitbook/TypeScript/_book/doc/handbook/tsconfig.json.html 如果一个目录下存在一个tsco ...

  2. create-react-app 搭建的项目中,使用 stylus

    相关介绍文章: react学习系列1 修改create-react-app配置支持stylus:https://www.jianshu.com/p/9cd7a0dff11f 在react中使用styl ...

  3. HTTP 状态码的完整列表

    一.1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态码.SC_CONTINUE = 100; 100(继续)请求者应当继续提出请求.服务器返回此代码表示已收到请求的第一部分,正在等待其余 ...

  4. python 计算校验和

    校验和是经常使用的,这里简单的列了一个针对按字节计算累加和的代码片段.其实,这种累加和的计算,将字节翻译为无符号整数和带符号整数,结果是一样的. 使用python计算校验和时记住做截断就可以了. 这里 ...

  5. Centos升级Python 2.7并安装pip、ipython

    https://www.cnblogs.com/technologylife/p/6242115.html

  6. Oracle迁移到MySQL性能下降的注意点(转)

    背景:最近有较多的客户系统由原来由Oracle改造到MySQL后出现了性能问题CPU 100%,或是后台的CRM系统复杂SQL在业务高峰的时候出现堆积导致业务故障.在我的记忆里面淘宝最初从Oracle ...

  7. ubuntu 脚本执行

    1.source命令用法: source FileName 作用:在当前bash环境下读取并执行FileName中的命令.该filename文件可以无"执行权限" 注:该命令通常用 ...

  8. quartz中设置Job不并发执行

    使用quartz框架可以完成定时任务处理即Job,比如有时候我们设置1个Job每隔5分钟执行1次,后来会发现当前Job启动的时候上一个Job还没有运行结束,这显然不是我们期望的,此时可以设置quart ...

  9. 【事务隔离级别】数据库事务隔离级别-UNDERSTANDING ISOLATION LEVELS

    参考链接:ISOLATION LEVELS ISOLATION LEVELS In a database system, concurrent transactions are processed i ...

  10. react基础

    上一篇文章主要是记录了自己是如何创建react项目的,今天则主要是总结一下react中的一个基础入门知识,包括数据定义和绑定.属性绑定.数组循环等等. 组件继承和挂载 当我们使用脚手架或者命令行创建一 ...