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

*/

原文地址:https://www.cnblogs.com/luoyibujue/p/10630135.html