题意:给你一个字符串,这个字符串我们可以把把他变成n个字符串按照以下规则:将当前字符串第一个放到字符串最后一位,字符串的下标依次向前推一位,比如:s[1] s[2 ]s[3] s[4]->s[2 ]s[3] s[4] s[1]...,然后问你字典序最小的和字典序最大的字符串在这n个字符串中的位置
解题思路:首先判定是否是循环串,然后用最小表示法和最大表示法来找出对应的位置,最小表示法可以找出比如一个环形的字符串,找出某个字符开始,然后这个字符串字典序最小;
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; char t[1005000]; int next1[1005000]; int tlen; void get_next() { int j=0,k=-1;next1[0]=-1; while(j<tlen) { if(k==-1||t[j]==t[k]) next1[++j]=++k; else k=next1[k]; } } int get_minstring(char *s) { int len = strlen(s); int i = 0, j = 1, k = 0; while(i<len && j<len && k<len) { int t=s[(i+k)%len]-s[(j+k)%len]; if(t==0) k++; else { if(t > 0) i+=k+1; else j+=k+1; if(i==j) j++; k=0; } } return min(i,j); } int get_maxstring(char *s) { int len = strlen(s); int i = 0, j = 1, k = 0; while(i<len && j<len && k<len) { int t=s[(i+k)%len]-s[(j+k)%len]; if(t==0) k++; else { if(t > 0) j+=k+1; else i+=k+1; if(i==j) j++; k=0; } } return min(i,j); } int main() { while(scanf("%s",t)!=EOF) { tlen=strlen(t); get_next(); int minn=get_minstring(t); int maxx=get_maxstring(t); int l=tlen-next1[tlen]; if(tlen%l==0&&l!=0) { printf("%d %d %d %d ",minn+1,tlen/l,maxx+1,tlen/l); } else { printf("%d 1 %d 1 ",minn+1,maxx+1); } } }