洛谷P3975 [TJOI2015]弦论 (后缀自动机sam求第k小子串)

题目描述

为了提高智商,ZJY开始学习弦论。这一天,她在《 String theory》中看到了这样一道问题:对于一个给定的长度为n的字符串,求出它的第k小子串是什么。你能帮帮她吗?

输入格式

第一行是一个仅由小写英文字母构成的字符串s

第二行为两个整数t和k,t为0则表示不同位置的相同子串算作一个,t为1则表示不同位置的相同子串算作多个。k的意义见题目描述。

输出格式

输出数据仅有一行,该行有一个字符串,为第k小的子串。若子串数目不足k个,则输出-1。

学习了后缀自动机 也终于A了这道感觉很麻烦的题= = 写个博客庆祝一下

求第k小串的套路就像是在主席树上面查询第k小数,首先用后缀自动机处理出每个节点后续的子串的个数,然后对于每个节点枚举26条边转移即可 一个节点所表示的串的出现次数即为endpos集合的size,若对于t = 1相同子串不同位置算不同子串(除复制节点外,其他节点初始|endpos|大小设置为1) 需要在后缀树上面拓扑dp t = 0的话 每个节点只表示它的最长串 所以每个节点的值为1 

 

#include
using namespace std;
#pragma GCC optimize(2)
#define Sheryang main
typedef long long ll;
#define HEAP(...) priority_queue<__VA_ARGS__ >
#define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >
template inline T min(T &x,const T &y){return x>y?y:x;}
template inline T max(T &x,const T &y){return x sum[1]){
			printf("-1");
		}else{
			Fuck(1,k);
		}
		puts("");
	}
}Sam;

char s[maxn];
int Sheryang(){
	scanf("%s",s);
	for(int i=0;s[i];i++){
		Sam.ins(s[i]-'a');
	}
	Sam.Solve();
	return 0; 
}

 

你可能感兴趣的:(后缀自动机sam)