题意:给几个字符串,求每个字符串的最小循环表示,最大循环表示(输出序号最小的)以及出现的次数。
思路:前面两个直接用模板可求解。出现次数实际上就是问循环节的个数,这时我们可以想到KMP算法中的nextval数组。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000001;
int nextval[maxn];
char str[maxn];
void get_nextval(char s[],int len)
{
long long i=0;
nextval[0]=-1;
long long j=-1;
while(i<len)
{
if(j==-1||s[i]==s[j])
{
i++;
j++;
nextval[i]=j;
}
else
j=nextval[j];
}
}
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=i+k+1;
else
j=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=j+k+1;
else
i=i+k+1;
if(i==j)
j++;
k=0;
}
}
return min(i,j);
}
int main()
{
while(scanf("%s",str)!=EOF)
{
int len=strlen(str);
get_nextval(str,len);
int len1=len-nextval[len];
int num=1;
if(len%len1==0)
num=len/len1; //稍微思考一下,就会想通,这个就是循环节出现的次数,也就是我们最后想要的num
printf("%d %d %d %d\n",get_minstring(str)+1,num,get_maxstring(str)+1,num);
}
return 0;
}