后缀数组模板

const int Maxn = 2 * 1e5;
const int Inf = 0x3f3f3f3f;

int sa[Maxn + 5], id_bak[Maxn + 5];
//sa[i] len + 1 ~ 2 * len 排名为 i 的串的编号
//id_bak[i] 编号为 i 的串该被放进哪个桶 
int sort_id[Maxn + 5], poi_bak[Maxn + 5];
//sort_id[i] 按照 len + 1 ~ 2 * len 排序的排名为 i 的串的编号 
//poi_bak[i] 当前队列的最后一个元素的排名 
int tem[Maxn * 2 + 5]; 
void Init_Bak (int n, int m) {//基数排序,装桶 
	rep (i, 1, m)
		poi_bak[i] = 0;
	rep (i, 1, n)
		poi_bak[id_bak[i]]++;
	rep (i, 1, m)
		poi_bak[i] += poi_bak[i - 1];
}
void Sort_L (int n) {//按照 len + 1 ~ 2 * len 排序 
	per (i, n, 1)
		sa[poi_bak[id_bak[sort_id[i]]]--] = sort_id[i];
}
void Get_Sa (int n, int m, char *str) {
	rep (i, 1, n) {
		id_bak[i] = str[i];
		sort_id[i] = i;
	}
	Init_Bak (n, m);
	Sort_L (n);
	
	for (int len = 1; len < n; len <<= 1) {
		Init_Bak (n, m);
		int Now_Rank = 0;
		rep (i, n - len + 1, n) {
			sort_id[++Now_Rank] = i;
		}
		rep (i, 1, n)
			if (sa[i] > len)
				sort_id[++Now_Rank] = sa[i] - len;
		Sort_L (n);
		
		rep (i, 1, n) tem[i] = id_bak[i];
		Now_Rank = 1; id_bak[sa[1]] = 1;
		rep (i, 2, n) {
			if (tem[sa[i - 1]] != tem[sa[i]] || tem[sa[i - 1] + len] != tem[sa[i] + len])
				Now_Rank++;
			id_bak[sa[i]] = Now_Rank;
		}
		m = Now_Rank;
	}
}
int H[Maxn + 5], Height[Maxn + 5];
void Get_Height (int n, char *str) {
	rep (i, 1, n) {
		H[i] = Max (H[i - 1] - 1, 0);
		if (id_bak[i] == 1) continue;
		while (str[i + H[i]] == str[sa[id_bak[i] - 1] + H[i]]) {
			H[i]++;
		}
	}
	rep (i, 1, n) {
		Height[i] = H[sa[i]];
	}
}
posted @ 2022-01-24 21:31  C2022lihan  阅读(10)  评论(0编辑  收藏  举报