【文文殿下】[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)问题. 例如:他可以查询一个字符串在另一个字符串中出现的所有子串,以及查询一个字符串中本质不同的字符串的个 ...
 
随机推荐
- openAL在mac下播放音源结束时判断处理
			
音频播放完毕,自然停止 alGetSourcei(source[0], AL_BUFFERS_QUEUED, &state); NSLog(@"queued number:%d ...
 - HDFS NameNode HA 部署文档
			
简介: HDFS High Availability Using the Quorum Journal Manager Hadoop 2.x 中,HDFS 组件有三个角色:NameNode.DataN ...
 - python's decorator&wrapper
			
[python's decorator&wrapper] decorator A function returning another function, usually applied as ...
 - leetcode 20 Valid Parentheses 有效的括号
			
描述: 给定一些列括号,判断其有效性,即左括号有对应的有括号,括号种类只为小,中,大括号. 解决: 用栈. bool isValid(string s) { stack<char> st; ...
 - xshell上传下载文件(Windows、Linux)
			
经常有这样的需求,我们在Windows下载的软件包,如何上传到远程Linux主机上?还有如何从Linux主机下载软件包到Windows下:之前我的做法现在看来好笨好繁琐,不过也达到了目的,笨人有本方法 ...
 - 在 macOS 中激活 Astash Professional
			
Astah Professional v7.2.0-1ff236版安装完毕后,直接用压缩包内的 astah-pro.jar 替换原安装目录内的同名文件(/Applications/astah prof ...
 - shell 用环境变量的值修改properties文件
			
假设有如下属性文件 demo.properties user.name=test user.password=123456 ............................... 需求:先需要 ...
 - 使用word 2010 发布csdn博客
			
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
 - Ubuntu 16.04调节屏幕显示字体大小
			
对于高分辨屏幕来说,Ubuntu的字体可能会有点小,反之,低分率的屏幕字体有点大,设置方法如下: [System Settings]->[Displays]->[ Scale for me ...
 - POJ3281 Dining                                                                                            2017-02-11 23:02             44人阅读              评论(0)              收藏
			
Dining Description Cows are such finicky eaters. Each cow has a preference for certain foods and dri ...