【BZOJ3277】串

【题目链接】

【双倍经验链接】

【思路要点】

  • 补档博客,无题解。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	200005
#define MAXL	100005
struct Suffix_Automaton {
	map <char, int> child[MAXN];
	int father[MAXN], depth[MAXN];
	int root, size, last, timer;
	vector <int> colour[MAXN], a[MAXN];
	int num[MAXN], right[MAXN], home[MAXN], value[MAXN];
	long long ans[MAXN];
	int new_node(int dep) {
		depth[size] = dep;
		father[size] = 0;
		child[size].clear();
		colour[size].clear();
		a[size].clear();
		num[size] = right[size] = 0;
		value[size] = 0;
		return size++;
	}
	void init() {
		size = 0;
		root = last = new_node(0);
	}
	void Extend(char ch, int col) {
		int np = child[last][ch];
		if (np) {
			if (depth[np] == depth[last] + 1)  {
				colour[np].push_back(col);
				last = np;
			} else {
				int nq = new_node(depth[last] + 1);
				father[nq] = father[np];
				father[np] = nq;
				child[nq] = child[np];
				for (int p = last; child[p][ch] == np; p = father[p])
					child[p][ch] = nq;
				colour[nq].push_back(col);
				last = nq;
			}
		} else {
			int np = new_node(depth[last] + 1);
			int p = last;
			for (; child[p][ch] == 0; p = father[p])
				child[p][ch] = np;
			if (child[p][ch] == np) {
				colour[np].push_back(col);
				last = np;
				return;
			}
			int q = child[p][ch];
			if (depth[q] == depth[p] + 1) {
				father[np] = q;
				colour[np].push_back(col);
				last = np;
				return;
			} else {
				int nq = new_node(depth[p] + 1);
				father[nq] = father[q];
				father[np] = father[q] = nq;
				child[nq] = child[q];
				for (; child[p][ch] == q; p = father[p])
					child[p][ch] = nq;
				colour[np].push_back(col);
				last = np;
			}
		}
	}
	void insert(char *s, int col) {
		int len = strlen(s + 1);
		last = root; ans[col] = 0;
		for (int i = 1; i <= len; i++)
			Extend(s[i], col);
	}
	void work(int pos) {
		num[pos] = ++timer;
		home[timer] = pos;
		for (unsigned i = 0; i < a[pos].size(); i++)
			work(a[pos][i]);
		right[pos] = timer;
	}
	void build() {
		for (int i = 1; i < size; i++)
			a[father[i]].push_back(i);
		work(0);
	}
	void dfs(int pos, long long sum) {
		for (unsigned i = 0; i < colour[pos].size(); i++)
			ans[colour[pos][i]] += sum;
		for (unsigned i = 0; i < a[pos].size(); i++)
			dfs(a[pos][i], sum + value[a[pos][i]]);
	}
} SAM;
struct Query {
	int home, l, r;
} Q[MAXN];
bool cmp(Query x, Query y) {
	return x.r < y.r;
}
int n, q, k, ans[MAXN];
int Last[MAXN], sum[MAXN];
char s[MAXL];
int query(int x) {
	int ans = 0;
	for (int i = x; i > 0; i -= i & -i)
		ans += sum[i];
	return ans;
}
void change(int x, int d) {
	for (int i = x; i <= SAM.timer; i += i & -i)
		sum[i] += d;
}
int main() {
	scanf("%d%d", &n, &k);
	SAM.init();
	for (int i = 1; i <= n; i++) {
		scanf("\n%s", s + 1);
		SAM.insert(s, i);
	}
	SAM.build();
	for (int i = 0; i < SAM.size; i++)
		Q[++q] = (Query) {i, SAM.num[i], SAM.right[i]};
	sort(Q + 1, Q + q + 1, cmp);
	int last = 0;
	for (int i = 1; i <= q; i++) {
		while (last < Q[i].r) {
			last++;
			int now = SAM.home[last];
			for (unsigned j = 0; j < SAM.colour[now].size(); j++) {
				int tmp = SAM.colour[now][j];
				if (Last[tmp]) change(Last[tmp], -1);
				change(last, 1);
				Last[tmp] = last;
			}
		}
		if (query(Q[i].r) - query(Q[i].l - 1) >= k)
			SAM.value[Q[i].home] = SAM.depth[Q[i].home] - SAM.depth[SAM.father[Q[i].home]];
	}
	SAM.dfs(SAM.root, 0);
	for (int i = 1; i <= n; i++)
		printf("%lld ", SAM.ans[i]);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值