字符串的最大最小表示法
感谢这篇博客:字符串的最小表示法
引言:一个长度为n的字符串可以将最后一位放在第一位,这样就有n种变形。如"bcaxe" 可以变成 :ebcax xebca axebc caxeb 这几种。
字符串的最大最小表示法,就是求着n种变形中的最大最小字典序的字符串,返回的值是第一个最大最小的字符串的起始字符位置,时间复杂度为O(n)。
思想:(最小表示法)
就是定义三个下标初始 i = 0, j = 1, k = 0;
(1) 如果s[i] < s[j] 那么 j++;
(2) 如果s[i] > s[j]明显 i 不是最小,i = j++;
(3) 如果s[i] == s[j], 那么就要用到 k ,以及一个性质,在 i 和 j 之间的字符一定是大于s[i]和s[j]的。令k = 0, 循环寻找第一个s[i+k] != s[j+k]的位置。若 s[i+k] < s[j+k] 那么 j += k+1, 因为s[i+k] < s[j+k] 那么从 i 开始的在i+k位是要比 j 开始的在j+k位更好一些。直接将j += k+1,然后在继续上面的s[i] 和 s[j] 的比较就行。在这里i 和 j 是等价的。 若s[!+k] > s[j+k], 与上述同理,直接令 i += k+1就行。
注意的是 i+k 和 j+k 可能会大于 n, 就要将其 %n。
下面贴代码:
#include <bits/stdc++.h>
using namespace std;
int GetMin(char *s){
int n = strlen(s);
int i = 0, j = 1, k = 0, t;
while(i < n && j < n && k < n){
t = s[(i+k)%n] - s[(j+k)%n];
if(!t) k++;
else{
if(t > 0) i += k+1;
else j += k+1;
if(i == j) j++;
k = 0;
}
}
return i < j ? i : j;
}
int GetMax(char *s){
int n = strlen(s);
int i = 0, j = 1, k = 0, t;
while(i < n && j < n && k < n){
t