【文文殿下】[BZOJ3277] 串
Description
字符串是oi界常考的问题。现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中
至少k个字符串的子串(注意包括本身)
Input
第一行两个整数n,k。
接下来n行每行一个字符串。
n,k,l<=100000
Output
输出一行n个整数,第i个整数表示第i个字符串的答案。
Sample Input
3 1
abc
a
ab
Sample Output
6 1 3
题解
多个字符串,考虑建广义后缀自动机。
对于每个节点,记录它在每个字符串出现的次数。
但是为了防止重复记录(一个字符串在他的SAM上可能多次匹配到同一个点),我们对每个节点记录一个“上一次统计到的是哪个字符串”,这样子进行有序增加。
当这个字符串跑到某一个节点时,我们把从这个节点,沿着parent树直到根部全部增加。因为一个串在匹配的时候,有可能绕过了他的parent直接匹配到该节点。
然后,对于每一个串,再跑一边。当他的右端点匹配到某个状态以后,立即进行“清算”,把它能够匹配的后缀全部统计。即:沿着Parent树全部加入答案。
但是这样是n^2的,我们预处理前缀和可以做到O(n)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
typedef long long ll;
const int maxn = 2e5+20;
ll ans=0;
int tmp[maxn];
int par[maxn],mx[maxn],tr[maxn][26];
char A[maxn>>1];
int f[maxn];
int cnt = 1,last = 1,Right[maxn];
int c[maxn],id[maxn];
int pre[maxn];
std::string S[maxn];
int n,k;
void extend(int x) {
int p = last;
if(tr[p][x]&&mx[tr[p][x]]==mx[p]+1) {last=tr[p][x];return;}
int np=++cnt;
mx[np]=mx[p]+1;
while(p&&!tr[p][x]) tr[p][x]=np,p=par[p];
if(!p) par[np]=1;
else {
int q = tr[p][x];
if(mx[q]==mx[p]+1) par[np]=q;
else {
int nq = ++cnt;
mx[nq]=mx[p]+1;
memcpy(tr[nq],tr[q],sizeof tr[q]);
par[nq]=par[q];
par[q]=par[np]=nq;
while(p&&tr[p][x]==q) tr[p][x]=nq,p=par[p];
}
}
last = np;
return;
}
inline void topsort() {
for(int i = 1;i<=cnt;++i) ++c[mx[i]];
for(int i = 1;i<=cnt;++i) c[i]+=c[i-1];
for(int i = 1;i<=cnt;++i) id[c[mx[i]]--]=i;
return;
}
int main() {
scanf("%d%d",&n,&k);
for(int i = 1;i<=n;++i) {
scanf("%s",A);
S[i]=std::string(A);
int len = S[i].length();
last = 1;
for(int j = 0;j<len;++j) extend(S[i][j]-'a');
}
for(int i = 1;i<=n;++i) {
int len = S[i].length();
int cur = 1;
for(int j = 0;j<len;++j) {
int c = S[i][j]-'a';
while(cur&&!tr[cur][c]) cur=par[cur];
if(!cur) cur=1;
else cur = tr[cur][c];
int tmp = cur;
if(tmp&&pre[tmp]!=i) pre[tmp]=i,++Right[tmp],tmp=par[tmp];
}
}
topsort();
//Right[1]=0;
for(int i = 1;i<=cnt;++i) f[id[i]]=f[par[id[i]]]+(Right[id[i]]>=k?mx[id[i]]-mx[par[id[i]]]:0);
for(int i = 1;i<=n;++i) {
int len = S[i].length();
int cur=1,L=0;
ll ans = 0;
for(int j = 0;j<len;++j) {
int c = S[i][j]-'a';
while(cur&&!tr[cur][c]) cur=par[cur];
if(!cur) cur=1,L=0;
else L=std::min(L,mx[cur])+1,cur = tr[cur][c];
if(L==mx[cur]||Right[cur]<k)
ans+=f[cur];
else {
ans+=f[cur];
ans-=mx[cur];
ans+=L;
}
}
printf("%lld ",ans);
}
return 0;
}
【文文殿下】[BZOJ3277] 串的更多相关文章
- BZOJ3473&&BZOJ3277串
BZOJ3473&&BZOJ3277串 题面 自己找去 HINT 对于所有串建立一个广义后缀自动机,对于每一个节点开一个set表示这个节点接受的子串在哪些串里出现过,然后在parent ...
- BZOJ3277 串(后缀数组+二分答案+主席树)
因为不会SAM,考虑SA.将所有串连起来并加分隔符,每次考虑计算以某个位置开始的子串有多少个合法. 对此首先二分答案,找到名次数组上的一个区间,那么只需要统计有多少个所给串在该区间内出现就可以了.这是 ...
- BZOJ3277——串
0.题意:给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 1.分析:这个题我问了吴大爷做法 首先建立后缀自动机,然后利用离线搞出每一个 ...
- bzoj3277 串 (后缀数组+二分答案+ST表)
常见操作:先把所有串都连到一起,但中间加上一个特殊的符号(不能在原串中/出现过)作为分割 由于全部的子串就等于所有后缀的所有前缀,那我们对于每一个后缀,去求一个最长的前缀,来满足这个前缀在至少K个原串 ...
- 【文文殿下】WC2019游记
Day0 今天早上三点半才睡着,五点起床,前往省城郑州.与省实验常老师汇合,坐上高铁,下午三点半多才到广州二中. 下午随便找了一个教室进去敲一敲代码,发现自己越来越菜了. 和一大堆网上的dalao面基 ...
- 【文文殿下】NOIp2018游记
Day-1 本段更新于 2018年11月8日23:26:44 今天还在机房里面,无所事事吧.上午睡了一上午,出去理了一下发,花了20块钱 QAQ. 下午来到机房,复习了一下exgcd的东西. 发现自己 ...
- 【文文殿下】【CF724C】Ray Tracing (中国剩余定理)
题解 我们考虑将棋盘扩大一倍,这样相当于取膜.然后,我们只要对x,y,的位置分类讨论,做四次crt就行.具体细节看文文代码. #include<cstdio> #include<al ...
- bzoj3473: 字符串 && bzoj3277串
3473: 字符串 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 121 Solved: 53[Submit][Status][Discuss] D ...
- 【文文殿下】后缀自动机(Suffix Automaton,SAM)学习笔记
前言 后缀自动机是一个强大的数据结构,能够解决很多字符串相关的(String-related)问题. 例如:他可以查询一个字符串在另一个字符串中出现的所有子串,以及查询一个字符串中本质不同的字符串的个 ...
随机推荐
- CCS5配置使用GenCodecPkg生成CODEC SERVER
1. 引言 CCS5中集成了算法生成工具的插件,使用XDAIS Tools条目里面的GenAlg命令生成的算法框架如下: 不过,我没找到如何在CCS中使用这个工程.难不成要把这个框架文件放在Linux ...
- Windows安装MySQL教程
一.下载MySQL MySQL官网首页 --> Download --> Community --> 选择“ MySQL Community Server” 即:MySQL下载连接 ...
- Theoretical & Applied Mechanics Letters第2届编委会2015年度第1次全体编委会工作会议纪要(转自力学学会)
2015年7月26日, Theoretical & Applied Mechanics Letters (TAML)第2届编委会在中国科学院力学研究所召开2015年第1次 全体编委工作会议.主 ...
- ADT离线安装
1.安装eclipse软件.安装后点击HELP菜单,找到下面的Install New Software并点击. 2.之后会弹出一个对话框,然后我们点击add,接下来弹出ADD对话框,然后我们再点击ar ...
- Code First 之类继承
关于Entity Framework 的code first 模式,相信大家都不陌生了.本文就来看看实体继承在 codefirst里的用法. 第一步 添加 code first 的环境 这里为了方便 ...
- Linux confluence5.8.10 wiki安装
选择首先需要java环境 其次需要mysql mysql安装请参考: http://www.cnblogs.com/syuf/p/7818710.html 安装好mysql之后,创建一个库 # mys ...
- NLTK和Stanford NLP两个工具的安装配置
这里安装的是两个自然语言处理工具,NLTK和Stanford NLP. 声明:笔者操作系统是Windows10,理论上Windows都可以: 版本号:NLTK 3.2 Stanford NLP 3.6 ...
- PHP开启页面报错的代码
PHP开启页面报错的方法很简单,在<?php内加入下面的代码就可以了: <?php ini_set("display_errors", "On"); ...
- centos环境下创建数据库和表的方法
centos环境下创建数据库和表的方法 //查询数据库的命令: mysql> SHOW DATABASES; +--------------------+ | Database ...
- Android 通过adb shell命令查看内存,CPU,启动时间,电量等信息
1. 查看内存信息 1)查看所有内存信息 命令: dumpsys meminfo 例: C:\Users\laiyu>adb shell shell@android:/ $ dumpsys m ...