题意:给你一个字符串,这个字符串我们可以把把他变成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\n",minn+1,tlen/l,maxx+1,tlen/l);
}
else
{
printf("%d 1 %d 1\n",minn+1,maxx+1);
}
}
}