hdu3374(最小最大表示法以及kmp)

题意:输出一个环形字符串的最小字典序的首位置,以及最大字典序的首位置,以及这个字符串的原字符串的循环节.......

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define M 1000020
int next[M];
char s[M];
void getnext()
{
    int i=0,j=-1;
    next[0]=-1;
    int len=strlen(s);
    while(i<len)
    {
        if(j==-1||s[i]==s[j])
        {
            i++;
            j++;
            next[i]=j;
        }
        else
            j=next[j];
    }
}
int workzx(int m,char str[]) 
{ 
    int i,j,l; 
    i=0; j=1; 
    while(i<m && j<m) 
    { 
        for(l=0;l<m;l++)  
            if(str[(i+l)%m]!=str[(j+l)%m]) break; 
        if(l>m) break; 
        if(str[(i+l)%m] > str[(j+l)%m]) 
            i=i+l+1; 
        else
            j=j+l+1; 
        if(i==j) j=i+1; 
    } 
    if(i<j) return i; 
    return j; 
}
int workzd(int len,char pat[])  //最大表示法 
{ 
   //int len = strlen(pat); 
   int i=0,j=1,k=0; 
   while(i<len && j<len && k<len) 
   { 
       int t = pat[(i+k)%len] - pat[(j+k)%len]; 
       if(!t) k++; 
       else
       { 
           if(t>0) j = j+k+1; 
           else i = i+k+1; 
           if(i == j) j++; 
           k = 0 ; 
       } 
   } 
   return i<j?i:j; 
} 

int main()
{
	int n;
	while(scanf("%s",s)>0)
	{
		int len=strlen(s);
		int cnt1=workzx(len,s);
		int cnt2=workzd(len,s);
		getnext();
		int sum=0;
		if(len%(len-next[len])==0)
		sum=len/(len-next[len]);
		else
		sum=1;
		printf("%d %d %d %d\n",cnt1+1,sum,cnt2+1,sum);
	}
	return 0;
}

 

posted @ 2013-08-08 11:22  紫忆  阅读(728)  评论(0编辑  收藏  举报