P4070 [SDOI2016]生成魔咒(SAM板子题,求本质不同子串)

思路:每个加入一个字符,它对总体本质不同子串的贡献就是 m a x l e n [ n o w ] − m a x l e n [ l i n k [ n o w ] ] maxlen[now]-maxlen[link[now]] maxlen[now]maxlen[link[now]],还有就是这里的儿子范围分散,转移数组用map。

ll ans;
struct Suffix_Automata {//minlen[i]=maxlen[link[i]]+1;
	int maxlen[N << 1], link[N << 1], A[N << 1], tmp[N << 1],num[N<<1], Size, Last;
	map<int, int> trans[N << 1];//儿子很多时用map离散
	void init()
	{
		Size = Last = 1;
		//memset(trans, 0, sizeof trans);
	}
	void Qsort() { 
		//A[],排出一个按照 maxlen 从小到大的结点序列
		//num[],每个endpos[st]集合的大小
		for(int i = 1; i <= Size; i ++) tmp[maxlen[i]]++; 
		for(int i = 1; i <= Size; i ++) tmp[i] += tmp[i - 1]; 
		for(int i = 1; i <= Size; i ++) A[tmp[maxlen[i]]--] = i;
		for (int i =Size; i >= 1; i--) num[link[A[i]]] += num[A[i]];
	} 
	inline void Extend(int id) {
		int cur = (++Size), p;
		num[cur] = 1;
		maxlen[cur] = maxlen[Last] + 1;
		for (p = Last; p && !trans[p][id]; p = link[p]) trans[p][id] = cur;
		//对suffix_path(u->s)所有满足条件的节点加上转移到当前状态的剪头
		if (!p) link[cur] = 1;//情况1:suffixlink直接到初始化状态   
		else {
			int q = trans[p][id];
			if (maxlen[q] == maxlen[p] + 1) link[cur] = q;//特殊情况2
			else {//一般情况3
				int clone = (++Size);//拆一个状态出来
				maxlen[clone] = maxlen[p] + 1;
				trans[clone] = trans[q];
				//memcpy(trans[clone], trans[q], sizeof trans[q]);
				link[clone] = link[q];
				for (; p && trans[p][id] == q; p = link[p]) trans[p][id] = clone;
				link[cur] = link[q] = clone;
			}
		}
		ans = ans + maxlen[cur] - maxlen[link[cur]];
		Last = cur;
	}
}sam;
int a[N];
int main()
{
	//freopen("in.txt", "r", stdin);
	int n = in();
	f(i, 1, n)a[i] = in();
	sam.init();
	f(i, 1, n)
	{
		sam.Extend(a[i]);
		printf("%lld\n", ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值