题目

给定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 字符串 【广义后缀自动机】的更多相关文章

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

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

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

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

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

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

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

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

  5. 2018.12.22 bzoj3473: 字符串(后缀自动机+启发式合并)

    传送门 调代码调的我怀疑人生. 启发式合并用迭代写怎么都跑不过(雾 换成了dfsdfsdfs版本的终于过了233. 题意简述:求给出nnn个字串,对于每个给定的字串求出其有多少个字串在至少kkk个剩下 ...

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

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

  7. 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 ...

  8. BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机 后缀自动机 字符串

    https://www.lydsy.com/JudgeOnline/problem.php?id=3926 广义后缀自动机是一种可以处理好多字符串的一种数据结构(不像后缀自动机只有处理一到两种的时候比 ...

  9. [bzoj3277==bzoj3473]出现k次子串计数——广义后缀自动机+STL

    Brief Description 给定n个字符串,对于每个字符串,您需要求出在所有字符串中出现次数大于等于k次的子串个数. Algorithm Design 先建立一个广义后缀自动机,什么是广义后缀 ...

随机推荐

  1. [windows]桌面中添加我的电脑,我的文档和网上邻居图标

    xp系统: 操作步骤:桌面任意位置--〉右键--〉属性--〉桌面选项卡--〉自定义桌面--〉常规:勾选相关图标确定即可. win7系统: 操作步骤:桌面任意位置--〉右键--〉个性化--〉(右侧)更改 ...

  2. JavaScript数据格式验证探讨

    1.需求 修改某个文本框数据,要求对修改后的格式做验证(必须是数字). 注:实际需求比上述复杂,为了说明问题,这里特意简化了需求(如:对修改后数据依赖条件的判断,数据入库等). 2.关于NaN的探讨( ...

  3. (1)Ngixn 编译安装 (版本:1.12.1)

        1.创建用户和群组     groupadd nginx     创建一个用户,不允许登陆和不创主目录     useradd -s /sbin/nologin -g nginx -M ngi ...

  4. VMware网络适配器设置

    VMware网络连接主要有三种方式,分别是桥接,NAT和Host-only. 桥接:直接使用的是真实机的物理网卡(有线网卡,无线网卡),会占用局域网中的一个IP,因此在设置虚拟机IP时要避免与同网段的 ...

  5. X和面试随笔

    第一次参加了面试,面试官很好,我写的笔试和回答的都很差劲,虽然技术方面的回答我想抽自己,但是人家还是要了,给了我一个机会,很感谢. 第一道题:设计一个进销存系统的表结构设计 1:老板每天要知道卖出的货 ...

  6. 查看进程lsof

    查看8000端口 lsof -i :8000 杀死进程 pkill -ns <pid>

  7. Vue+webpack+echarts+jQuery=demo

    需要的插件: "dependencies": { "bootstrap": "^3.3.7", "echarts": & ...

  8. 前端知识点总结——HTML

    HTML:HTML4.01 指的就是网页技术HTML5:HTML4.01的升级版本 1.web的基础知识 web与Internet1.Internet:全球性的计算机互联网络,因特网,互联网,交互网2 ...

  9. Asp.Net Core 入门(十)—— 模型绑定和验证

    模型绑定时将Http请求中的数据映射到控制器操作方法上对应的参数,操作方法中的参数可以是简单类型,如整形,字符串等,也可以是复杂类型,如Product,Order等. Asp.Net Core MVC ...

  10. Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'userController' method

    在使用SpringMVC的时候遇到了这个问题 问题原因:  在指定方法所对应的url地址的时候重复了, 也就是@RequestMapping("url")中, 两个方法使用了同一个 ...