题意:
给你一串字符,这串字符可以左移(将最前面一个字符放到字符串最后面)生成 strlen(s) 个字符串,求出其中字典序最小 和 最大 的字符串在原串的起始位置和出现的次数(如果存在多个最小或最大串,则输出rank值小的,即下标小的那个)。
输出:最小字符串起始位置 出现次数 最大字符串起始位置 出现次数
思路:
字符串最大最小表示法+nxt[ ]应用
len = strlen(s);
len-nxt[len]即为字符串循环长度;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
char s[maxn];
int nxt[maxn];
void getnxt()
{
int len = strlen(s);
int i,j;
i = 0;
j = nxt[0] = -1;
while(i<len)
{
if(j==-1 || s[i]==s[j])
{
i++,j++;
if(s[i]==s[j])
nxt[i] = nxt[j];
else
nxt[i] = j;
}
else
j = nxt[j];
}
}
int getmin(char *p)
{
int len = strlen(p);
int i = 0,j = 1,k = 0;
while(i<len && j<len && k<len)
{
int t = p[(i+k)%len]-p[(j+k)%len];
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 *p)
{
int len = strlen(p);
int i = 0,j = 1,k = 0;
while(i<len && j<len && k<len)
{
int t = p[(i+k)%len]-p[(j+k)%len];
if(!t)
k++;
else
{
if(t>0)
j += k+1;
else
i += k+1;
if(i==j)
j++;
k = 0;
}
}
return i<j?i:j;
}
int main()
{
while(~scanf("%s",s))
{
getnxt();
int len = strlen(s);
int n = len-nxt[len];
printf("%d %d %d %d\n",getmin(s)+1,len/n,getmax(s)+1,len/n);
}
return 0;
}