最小表示法
作者:互联网
实现思路:
初始化i=0,j=1,k=0,即首先选择两个起始位置,然后比较这两个位置开始的字符串的字典序大小,k表示两个字符串前k个字母相同。
如果k+1个字母仍然相同,令k++; 否则,两个字符串已经比较出大小,大的那个应该被淘汰,但是我们已经比较了k位了,这些信息应该被派上用场。
因为我们已经比较出大小了(假设从i开始的字符串比j小),那么现在是得出了:①s[i:i+k]<s[j:j+k]、②s[i+k]<s[j+k]。
假设j=j+t,且t<=k,那么仍然会有s[i+t:i+k]<s[j+t:j+k],所以从j+t开始的字符串仍然不可能是最小的。
通过已经比较得到的信息,我们应该令j+=k+1。
最后特判,如果i==j,令j++/i++。
常见应用
1. 用于获取一个环的最小字典序。
2. 用于判断两个环是否相等(获取每个环的最小字典序表示法,这在表示上是唯一的,然后比较两个字符串是否一样)。
最小/大表示法模板:
查看代码
int n, m;
char a[maxn], b[maxn];
int MinPos(int n, char a[]) { // 最小表示法
if (n == 1) return 1;
int i = 1, j = 2, k = 0;
#define pos(x) ((x) > n ? (x)-n : (x))
while (i <= n && j <= n && k < n) { // k < n
if (a[pos(i + k)] == a[pos(j + k)]) {
k++;
} else {
// (a[pos(i + k)] > a[pos(j + k)]) ? j = j + k + 1 : i = i + k + 1;
(a[pos(i + k)] < a[pos(j + k)]) ? j = j + k + 1 : i = i + k + 1;
i += (i == j), k = 0; // if (i == j) i++; k重新置零
}
}
return min(i, j);
}
void solve() {
cin >> a + 1 >> b + 1;
int mna = MinPos(n = strlen(a + 1), a);
int mnb = MinPos(m = strlen(b + 1), b);
string ans;
for (int i = 1; i <= n; i++, mna = (mna % n) + 1, mnb = (mnb % n) + 1) {
ans.push_back(a[mna]);
if (a[mna] != b[mnb]) {
cout << "No" << endl;
return;
}
}
cout << "Yes\n" << ans << endl;
}
标签:MinPos,int,最小,pos,表示法,++,字符串 来源: https://www.cnblogs.com/guanjinquan/p/16305253.html