BZOJ3473 字符串 【广义后缀自动机】
题目
给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串?
输入格式
第一行两个整数n,k。
接下来n行每行一个字符串。
输出格式
一行n个整数,第i个整数表示第i个字符串的答案。
输入样例
3 1
abc
a
ab
输出样例
6 1 3
提示
对于 100% 的数据,1<=n,k<=105,所有字符串总长不超过105,字符串只包含小写字母。
题解
我们先建一个广义后缀自动机
然后用每个原串在SAM上走,走到的节点就是parent树的叶子节点,将其沿parent边一直往上+1,表示这些节点表示的字符串+1【当然只能加一次,所以再开一个数组cur[]表示加过没有】
处理完后,我们就可以统计答案了
先拓扑排序,设f[]为该位置满足题意的字符串个数,显然如果一个位置累加的字符串>=k,那么该位置表示的至少为\(step[u] - step[pre[u]]\)
但还不完全,父亲的代表的字符串个数同样也符合该点
然后每个串再在SAM上走一遍统计答案即可
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 200005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
string s[maxn];
char ss[maxn];
int ch[maxn][26],pre[maxn],step[maxn],sz[maxn],cnt,last,n,k,cur[maxn];
LL f[maxn];
int ins(int x){
int p = last,np = ++cnt; step[np] = step[p] + 1; last = np;
while (p && !ch[p][x]) ch[p][x] = np,p = pre[p];
if (!p) pre[np] = 1;
else {
int q = ch[p][x];
if (step[q] == step[p] + 1) pre[np] = q;
else {
int nq = ++cnt; step[nq] = step[p] + 1;
for (int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
pre[nq] = pre[q]; pre[np] = pre[q] = nq;
while (ch[p][x] == q) ch[p][x] = nq,p = pre[p];
}
}
return np;
}
int b[maxn],a[maxn];
LL ans;
void tsort(){
REP(i,cnt) b[step[i]]++;
REP(i,cnt) b[i] += b[i - 1];
for (int i = cnt; i; i--) a[b[step[i]]--] = i;
}
int main(){
n = read(); k = read();
last = cnt = 1;
for (int i = 1; i <= n; i++){
last = 1;
scanf("%s",ss); s[i] = string(ss);
int len = strlen(ss);
for (int i = 0; i < len; i++) ins(ss[i] - 'a');
}
int u;
for (int i = 1; i <= n; i++){
u = 1;
for (int j = 0; j < s[i].length(); j++){
u = ch[u][s[i][j] - 'a'];
for (int p = u; p && cur[p] != i; p = pre[p])
sz[p]++,cur[p] = i;
}
}
tsort();
sz[1] = 0;
for (int i = 1; i <= cnt; i++)
u = a[i],f[u] = f[pre[u]] + (sz[u] >= k ? step[u] - step[pre[u]] : 0);
for (int i = 1; i <= n; i++){
ans = 0; u = 1;
for (int j = 0; j < s[i].length(); j++){
u = ch[u][s[i][j] - 'a'];
ans += f[u];
}
printf("%lld ",ans);
}
return 0;
}
BZOJ3473 字符串 【广义后缀自动机】的更多相关文章
- BZOJ3473 字符串 广义后缀自动机
今天主攻了下SAM 好多东西以前都没理解到 对于这道题 我们建一个自动机存所有串 每个穿last从1开始 对于自动机上每个点额外记一个cnt 表示能匹配到这个点的不同串个数 建完对每个串在自动机上匹配 ...
- 【bzoj3277/bzoj3473】串/字符串 广义后缀自动机
题目描述 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 输入 第一行两个整数n,k.接下来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) ...
- 2018.12.22 bzoj3473: 字符串(后缀自动机+启发式合并)
传送门 调代码调的我怀疑人生. 启发式合并用迭代写怎么都跑不过(雾 换成了dfsdfsdfs版本的终于过了233. 题意简述:求给出nnn个字串,对于每个给定的字串求出其有多少个字串在至少kkk个剩下 ...
- BZOJ 3473 字符串 ——广义后缀自动机
这题就比较有趣了. 首先匹配一遍,然后统计子树叶子节点中包含大于等于k的节点个数(HH的项链) 然后就可以搞了. 关于合法的情况数,显然是l[i]-l[fa[i]],然后向下下传即可(YY一下). # ...
- bzoj 3277 串 && bzoj 3473 字符串 && bzoj 2780 [Spoj]8093 Sevenk Love Oimaster——广义后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3277 https://www.lydsy.com/JudgeOnline/problem.p ...
- BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机 后缀自动机 字符串
https://www.lydsy.com/JudgeOnline/problem.php?id=3926 广义后缀自动机是一种可以处理好多字符串的一种数据结构(不像后缀自动机只有处理一到两种的时候比 ...
- [bzoj3277==bzoj3473]出现k次子串计数——广义后缀自动机+STL
Brief Description 给定n个字符串,对于每个字符串,您需要求出在所有字符串中出现次数大于等于k次的子串个数. Algorithm Design 先建立一个广义后缀自动机,什么是广义后缀 ...
随机推荐
- IOS博客
http://www.cnblogs.com/lovecode/articles/2249548.html从这个人这里了解了一些关于uiview和uilayer的区别 以及对于渲染和动画也有了一些了解 ...
- 电脑连接海信电视 HDMI
注意:我们家的电视是海信的,所以不能代表所有的电视哦~~~ 家里电视有线电视已经过期很长时间了,早就想把电脑连接到电视上用电视做显示器的心了,今天来兴趣了,就弄了一下!!! 用电脑连接电视需要先解决两 ...
- ftl-server静态资源服务器
ftl-server 是一前端开发工具,支持解析freemarker模板,模拟后端接口,反向代理等功能. 特性 解析freemarker模板 静态资源服务 mock请求 代理请求 livereload ...
- JavaScript异步仿同步(控制流)的实现
在前端开发中尤其是在nodejs开发中经常会遇到这样的场景(以ajax为例):有3个(或者更多个)Ajax请求,并且第2个请求依赖于第1个,第3个请求依赖于第2个,那我们可能就会在发第一个Ajax后回 ...
- 如何关闭OSX 10.11 SIP (System Integrity Protection)
http://www.jianshu.com/p/0572336a0771 注意:SIP功能是Apple在OSX上推出的系统完整性保护功能,对于普通MAC用户来说是一项安全保护功能,如果不了解他的作用 ...
- Codeforces Round #272 (Div. 2)-C. Dreamoon and Sums
http://codeforces.com/contest/476/problem/C C. Dreamoon and Sums time limit per test 1.5 seconds mem ...
- 精选30道Java笔试题附答案分析
精选30道Java笔试题解答 都是一些非常非常基础的题,是我最近参加各大IT公司笔试后靠记忆记下来的,经过整理献给与我一样参加各大IT校园招聘的同学们,纯考Java基础功底,老手们就不用进来了,免得笑 ...
- vue for循环中常见问题 之 求和(合计)
例:求后台返回数据this.dataInfo 中某个字段(item.totalSum)的和,只需添加computed,然后模板中直接可以使用totalSumAll (不需要再data中声明) comp ...
- 一款App的开发成本是多少?
答一: 接触过上万名创业者,开发上线过超过30款App,没有比我更适合回答这个问题的了.. 本文对想做好一款App项目的人来说这是一篇价值百万的回答!因为这是我们花了几百万试错成本试出来的经验! &l ...
- Cscope的使用(领略Vim + Cscope的强大魅力)
文章出处:http://blog.csdn.net/dengxiayehu/article/details/6330200 Cscope的使用(领略Vim + Cscope的强大魅力) 1.Cscop ...