题意:给一个串s1,只包含0到7,用它构造出一个新串s2,输出新串循环移位可以得到的最小串。构造方式:s2[i] = s1[i+1] - s1[i].如果得到的新值小于0,那么就要加8.最后一位要用第一位来减。
思路:构造出新串之后最小表示法求解即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const int maxn = 300005;
typedef long long ll;
int MINR(char s[], int l){
for(int i=0; i<l; ++i){
s[l + i] = s[i];
}
s[2 * l] = 0;
int i = 0, j = 1;
while(i < l && j < l){
int k = 0;
while(s[i + k] == s[j + k] && k < l){
++k;
}
if(k == l) break;
if(s[i + k] > s[j + k]) i = max(i + k + 1, j + 1);
else j = max(j + k + 1, i + 1);
}
return i < j ? i : j;
}
char s1[maxn], s2[maxn * 2];
int main(){
while(~scanf("%s", s1)){
int len = strlen(s1);
for(int i=0; i<len; ++i){
if(i == len - 1){
s2[i] = (s1[0] - s1[i] + 8) % 8 + '0';
} else {
s2[i] = (s1[i + 1] - s1[i] + 8) % 8 + '0';
}
}
int pos = MINR(s2, len);
for(int i=0; i<len; ++i){
printf("%c", s2[i + pos]);
}
printf("\n");
}
return 0;
}