題目:
http://acm.hdu.edu.cn/showproblem.php?pid=3374
叫你求最小表示,和最大表示的開始位置(多個解輸出最前面的那個) , 和 表示的次數
方法: 最小最大表示法+ KMP
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
char s[1111111];
int next[1111111];
void getnext() {
int i=0,j=-1;
next[i]=-1;
while(s[i]) {
if(j==-1||s[i]==s[j])
i++,j++,next[i]=j;
else
j=next[j];
}
}
//最小表示
int minexp(char *s,int x) {
int i=0,j=1,k=0,t;
while(i<x&&j<x&&k<x) {
t=s[ (i+k)%x ]-s[ (j+k)%x ];
if(t==0) k++;
else {
if(t>0) i+=k+1;
else j+=k+1;
if(i==j) j++;
k=0;
}
}
return i<j?i:j;
}
//最大表示,只要把小於改成大於號
int maxexp(char *s,int x) {
int i=0,j=1,k=0,t;
while(i<x&&j<x&&k<x) {
t=s[ (i+k)%x ]-s[ (j+k)%x ];
if(t==0) k++;
else {
if(t<0) i+=k+1;
else j+=k+1;
if(i==j) j++;
k=0;
}
}
return i<j?i:j;
}
int main()
{
while(scanf("%s",s)!=EOF) {
int x=strlen(s);
//求最小表示,和最大表示
int pos1=minexp(s,x)+1;
int pos2=maxexp(s,x)+1;
int r;
getnext();
//求循環節,判斷循環次數
r=x-next[x];
if(x%r==0) r=x/r;
else r=1;
//因爲是同構,所以最小表示和最大表示的循環次數是一樣的
printf("%d %d %d %d\n",pos1,r,pos2,r);
}
}