1. 程式人生 > 其它 >P4070 [SDOI2016]生成魔咒(字尾自動機)

P4070 [SDOI2016]生成魔咒(字尾自動機)

支援在一個字串後面線上新增一個字元,同時每次詢問當前字串的本質不同子串數量。

字尾自動機好像有一個性質,就是線上新增字元的時候並不會影響link樹的形態,只是在link樹上新增一個節點?剛開始一知半解...

#include<bits/stdc++.h>
using namespace std;
const int maxn=4e5+100;
int len[maxn],link[maxn];
map<int,int> nxt[maxn];
int sz[maxn];
int tot=1,lst=1;
int n,x;
long long ans=0;
void sam_extend (int c) {
	int cur=++tot;
	len[cur]=len[lst]+1;
	sz[cur]=1;
	int p=lst;
	while (p&&!nxt[p][c]) {
		nxt[p][c]=cur;
		p=link[p];
	}
	if (!p) {
		link[cur]=1;
	}
	else {
		int q=nxt[p][c];
		if (len[p]+1==len[q]) {
			link[cur]=q;
		}
		else {
			int clone=++tot;
			len[clone]=len[p]+1;
			nxt[clone]=nxt[q];
			link[clone]=link[q];
			while (p&&nxt[p][c]==q) {
				nxt[p][c]=clone;
				p=link[p];
			}
			link[q]=link[cur]=clone;
		}
	}
	lst=cur;
	ans+=len[cur]-len[link[cur]];
}
int main () {
	scanf("%d",&n);
	for (int i=1;i<=n;i++) {
		scanf("%d",&x);
		sam_extend(x);
		printf("%lld\n",ans);
	}
}