String Rank
SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7
and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once.
Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.
abcder aaaaaa abababSample Output
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1000010
using namespace std;
char s[maxn];
int Next[maxn];
void getnext(char *s,int len)//求next數組以獲得循環節長度
{
Next[0]=Next[1]=0;
for(int i=1;i<len;i++)
{
int j=Next[i];
while(j&&s[i]!=s[j]) j=Next[j];
Next[i+1]=s[i]==s[j]?j+1:0;
}
}
int express(char *s,int len,int flag)//最小表示法求最小字典序的循環同構的起始位置
{
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(flag)//最小表示
{
if(!t) k++;
else if(t>0) i=i+k+1,k=0;
else j=j+k+1,k=0;
if(i==j) j++;
}
else//最大表示
{
if(!t) k++;
else if(t<0) i=i+k+1,k=0;
else j=j+k+1,k=0;
if(i==j) j++;
}
}
return min(i,j);
}
int main()
{
while(~scanf("%s",s))
{
int len=strlen(s);
int rank1=express(s,len,1)+1,rank2=express(s,len,0)+1;//flag設爲1是求最小字典序,設爲0是求最大
getnext(s,len);//kmp裏面求next數組的方法
int cnt=len/(len-Next[len]);//據說個數就是循環節的個數,最大最小都是一樣的
printf("%d %d %d %d\n",rank1,cnt,rank2,cnt);
}
return 0;
}