最小表示法学习小记

定义循环同构串——当字符串S中选定一个位置i满足S[i~n]+S[1-i-1]=T,最小表示发用来找到字符串中最小字典序的循环同构串。

类似KMP的思想。先破环成链,然后三指针比较。重点在于若 \(S[i+k]>S[j+k]\)\(i=i+k+1\),这一点将算法优化了很多。

模板题:

#include <bits/stdc++.h>

using namespace std;

int s[600005], n;

int zxbsf()
{
	for (int i = 1; i <= n; i++) {
		s[i + n] = s[i];
	}
	int i = 1, j = 2, k = 0;
	while (i <= n && j <= n) {
		for (k = 0; k <= n && s[i+ k] == s[j + k]; k++);
		s[i + k] > s[j + k] ? i = i + k + 1 : j = j + k + 1;
		if (i == j) j ++;
	}
	return min(i,j);
}

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> s[i];
	}
	int k = zxbsf();
	for (int i = 0; i < n; i++) {
		cout << s[i + k] << " ";
	} cout << endl;
	return 0;
}

每次向后扫描 \(k\) 的长度,则 \(i\)\(j\),最多向后移动 \(2n\) 的长度,所以时间复杂度是 \(O(n)\) 的。

posted @ 2023-01-28 09:26  Vegdie  阅读(26)  评论(0编辑  收藏  举报