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;

}

 

你可能感兴趣的:(HDU)