[洛谷P4070][SDOI2016]生成魔咒

题目大意:有一个字符串,每次在末尾加入一个字符,问当前共有多少个本质不同的字串

题解:$SAM$,就是问插入这个字符后,多了多少个字串,就是当前这个点的$Right$数组大小。

卡点:

 

C++ Code:

#include <cstdio>
#include <iostream>
#include <map>
#define maxn 100010
long long ans;
namespace SAM {
#define N (maxn << 1)
#define root 1
	int R[N], fail[N];
	std::map<int, int> nxt[N];
	int lst = root, idx = root;
	void append(int ch) {
		int p = lst, np = lst = ++idx;
		R[np] = R[p] + 1;
		for (; p && !nxt[p].count(ch); p = fail[p]) nxt[p][ch] = np;
		if (!p) fail[np] = root;
		else {
			int q = nxt[p][ch];
			if (R[p] + 1 == R[q]) fail[np] = q;
			else {
				int nq = ++idx;
				nxt[nq] = nxt[q], fail[nq] = fail[q], R[nq] = R[p] + 1, fail[np] = fail[q] = nq;
				for (; p && nxt[p].count(ch) && nxt[p][ch] == q; p = fail[p]) nxt[p][ch] = nq;
			}
		}
	}
	int query() {
		return R[lst] - R[fail[lst]];
	}
#undef root
#undef N
}

int n;
int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	std::cin >> n;
	for (int i = 0, x; i < n; i++) {
		std::cin >> x;
		SAM::append(x);
		std::cout << (ans += SAM::query()) << '\n';
	}
	return 0;
}

  

转载于:https://www.cnblogs.com/Memory-of-winter/p/10160817.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值