[TJOI2015]弦论

巨大缝合题(逃
先考虑\(k\)小操作啊,\(SAM\)除去\(link\)后,这个东西就类似于一颗\(tire\)
就在\(tire\)上跑就好了。
不过要预处理出每个等价类的出现次数。
这题充分揭示了后缀\(tire\)\(SAM\)的关系,\(SAM\)实际上为路径压缩后的后缀\(tire\)树的聚合体。

[TJOI2015]弦论
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define N 500005

ll link[N << 1],ch[N << 1][30],f[N << 1],g[N << 1],len[N << 1];

char a[N];

ll nod = 1,lst = 1;

inline void insert(int c){
	int p = lst,q = ++nod;lst = q;
	len[q] = len[p] + 1;
	while(!ch[p][c] && p != 0){//向上找 
		ch[p][c] = q;
		p = link[p];
	} 
	if(p == 0)
	link[q] = 1;
	else{
		int x = ch[p][c];
		if(len[p] + 1 == len[x]){
			link[q] = x;
		}else{
			int y = ++ nod ;//复制一个新节点
			link[y] = link[x];
			link[x] = link[q] = y;
			len[y] = len[p] + 1;
			std::memcpy(ch[y],ch[x],sizeof(ch[x])); 
			while(p != 0 && ch[p][c] == x){
				ch[p][c] = y;
				p = link[p];
			}
		}
	}
}

ll cnt,head[N << 1];
struct P{int to,next;}e[N << 1];

inline void add(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}

inline void dfs(int u){
	if(head[u] == 0){
		f[u] = 1;
		return;
	}
	for(int i = head[u];i;i = e[i].next){
		dfs(e[i].to);
		f[u] += f[e[i].to];
	}
}

ll t,k;
bool vis[N << 1];

inline void dfs2(int u){
	if(vis[u])
	return ;
	vis[u] = 1;
	for(int i = 0;i <= 26;++i){
		if(!ch[u][i])
		continue;
		dfs2(ch[u][i]);
		g[u] += g[ch[u][i]];
	}
}

inline void Print(int u,int k){
//	std::cout<<u<<" "<<k<<" "<<f[u]<<std::endl;
	if(k <= f[u])return ;else k -= f[u];
	for(int i = 0;i <= 26;++i){
		if(!ch[u][i])
		continue;
		if(g[ch[u][i]] >= k){
		std::cout<<(char)('a' + i);
		Print(ch[u][i],k);
		return;
		}
		else
		k -= g[ch[u][i]];
	}
}

int main(){
	freopen("q.in","r",stdin);
	freopen("q.out","w",stdout);
	scanf("%s",a + 1);
	ll l = std::strlen(a + 1);
	scanf("%lld%lld",&t,&k);
	for(int i = 1;i <= l;++i)
	insert(a[i] - 'a');
	for(int i = 1;i <= nod;++i)
	add(link[i],i);
	dfs(1);
	for(int i = 1;i <= nod;++i)
	g[i] = (t) ? f[i] : (f[i] = 1);
	f[1] = g[1] = 0;
	dfs2(1);
	for(int i = 1;i <= nod;++i)
	std::cout<<f[i]<<" "<<g[i]<<std::endl;
	if(k > g[1]){
		puts("-1");
		return 0;
	}
	Print(1,k);
}

posted @ 2021-06-10 21:57  fhq_treap  阅读(58)  评论(0编辑  收藏  举报