BZOJ 3473: 字符串 (广义后缀自动机)
/*
广义后缀自动机, 每次加入维护 该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: 字符串 (广义后缀自动机)的更多相关文章
- 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) ...
 - BZOJ 3473 字符串 ——广义后缀自动机
		
这题就比较有趣了. 首先匹配一遍,然后统计子树叶子节点中包含大于等于k的节点个数(HH的项链) 然后就可以搞了. 关于合法的情况数,显然是l[i]-l[fa[i]],然后向下下传即可(YY一下). # ...
 - bzoj 3277: 串 & bzoj 3473: 字符串【后缀自动机||后缀数组】
		
建一个广义后缀自动机(每加完一个串都返回root),在parent树上dpsum记录合法长度,打着时间戳往上跳,最后每个串在自动机上跑一变统计答案即可. 后缀数组理解起来可能方便一点,但是难写,就只说 ...
 - BZOJ 3277 串 (广义后缀自动机)
		
3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] De ...
 - 【bzoj3277/bzoj3473】串/字符串  广义后缀自动机
		
题目描述 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 输入 第一行两个整数n,k.接下来n行每行一个 ...
 - BZOJ 2894: 世界线 广义后缀自动机
		
Code: #include<bits/stdc++.h> #define maxn 300000 #define ll long long using namespace std; ve ...
 - bzoj 3926 转换+广义后缀自动机
		
思路:重点在于叶子节点只有20个,我们把叶子节点提到根,把20个trie图插入后缀自动机,然后就是算有多少个本质不同的字串. #include<bits/stdc++.h> #define ...
 - BZOJ 4180: 字符串计数 后缀自动机 + 矩阵乘法 + 二分(神题)
		
Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999. 他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C ...
 - BZOJ3473 字符串 广义后缀自动机
		
今天主攻了下SAM 好多东西以前都没理解到 对于这道题 我们建一个自动机存所有串 每个穿last从1开始 对于自动机上每个点额外记一个cnt 表示能匹配到这个点的不同串个数 建完对每个串在自动机上匹配 ...
 
随机推荐
- ASP.NET中JSON的序列化和反序列化(转)
			
JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介绍 ...
 - Spring AOP + PageHelper分页
			
1.增加依赖配置 <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweav ...
 - 【转】Lambda表达式详解
			
前言 1.天真热,程序员活着不易,星期天,也要顶着火辣辣的太阳,总结这些东西. 2.夸夸lambda吧:简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1.0后新增的最重要的功能之一 ...
 - 前端大神讲解,初级程序与高级程序写表格变色的区别,dom 0 与dom 1
			
我们在遇到表格行数太多时,往往会眼花缭乱,下一行看成对应上一行.就要遇到写鼠标移动那行,那行高亮显示. 这里用到一个this关键字: 在面向对象里,this代表对象本身. 在这里只要记住,谁调用这个函 ...
 - Hadoop错误集:Could not find the main class: org.apache.hadoop.*
			
在搭建Hadoop机群的时候,之前遇见了很多次找不到类的错误,因为对Hadoop了解不深,所以就在网上漫无目的的找解决方案,所以这里总结下我用的方法. 解决办法一: 我之前遇到了找不到 org.apa ...
 - USB-IF协会公布最新PD3.0(PPS)协议认证芯片和产品名单
			
原文: http://www.chongdiantou.com/wp/archives/25510.html 2017年的骁龙技术峰会高通带来了第一款兼容USB PD3.0(PPS)的QC4+充电器, ...
 - 字符编码-ASCII,GB2312,GBK,GB18030
			
ASCII ASCII,GB2312,GBK,GB18030依次增加,向下兼容. 手机只需要支持GB2312 电脑中文windows只支持GBK 发展历程 如果你使用编译器是python2.0版本,默 ...
 - dell 7447加装SSD
			
老本加新件:) dell 7447第一款游匣? 14年冬入手,陪伴在下已有4年 一.需要拆机看接口(不知道的话),拆机无流程,网上一大把,此处不再赘述. 二.硬盘接口知识扩展: SATA3 m2接口有 ...
 - google chrome浏览器 程序无法启动并行配置不正确
			
启动电脑后打开chrome弹出如下信息: 系统:win7 进入chrome的安装路径 C:\Program Files (x86)\Google\Chrome\Application 两个版本文件夹, ...
 - 文件上传(asp.net webform中)
			
1.配置允许上传文件大小 <configuration> <appSettings> <!--配置上传文件最大字节数:单位KB--> <add key=&qu ...