题目大意:给你一个字符串,问这个字符串经过移动后的字典序最小的字符串的首字符位置和字典序最大的字符串的首字符的位置,和能出现多少次最小字典序的字符串和最大字典序的字符串
解题思路:能出现多少次,就要看循环节有多少个了
剩下的就是最小表示法和最大表示法的裸题了
#include <cstdio>
#include <cstring>
const int N = 1000010;
char str[N];
int len;
int next[N];
void getFail() {
len = strlen(str);
int i = 0, j = -1;
next[0] = -1;
while (i < len) {
if (j == -1 || str[i] == str[j]) {
i++; j++;
next[i] = j;
}
else j = next[j];
}
}
int getMin() {
int i = 0, j = 1;
int l;
while (i < len && j < len) {
for (l = 0; l < len; l++)
if (str[(i + l) % len] != str[(j + l) % len]) break;
if (l >= len) break;
if (str[(i + l) % len] > str[(j + l) % len]) i = i + l + 1;
else j = j + l + 1;
if (i == j) j++;
}
return i < j ? i : j;
}
int getMax() {
int i = 0, j = 1, k = 0;
while (i < len && j < len && k < len) {
int t = str[(i + k) % len] - str[(j + k) % len];
if (!t) k++;
else {
if (t > 0) j = j + k + 1;
else i = i + k + 1;
if (i == j) j++;
k = 0;
}
}
return i < j ? i : j;
}
int main() {
while (scanf("%s", str) != EOF) {
getFail();
int Min = getMin();
int Max = getMax();
int c = 0;
if (len % (len - next[len]) == 0)
c = len / (len - next[len]);
else c = 1;
printf("%d %d %d %d\n", Min + 1, c, Max + 1, c);
}
return 0;
}