您的位置:首页 > 其它

hdu3374 最小最大表示法kmp求循环节

2015-09-16 10:32 393 查看
题意:一个字符串的同构串中字典序最小的跟字典序最大,都要求输出起始下标最小的,然后这两个同构串在所有同构串中出现的次数。

求字典序最小最大直接最小最大表示法。出现次数的话,如果该字符串能多次出现一个同构串,那么这个字符串的循环节要大于1,不然就只能出现一次,所以用kmp求一下循环节就行了
#include <iostream>
#include <string.h>
#include <cstdio>
using namespace std;
const int N=1000010;
int len,nextt
;
char str
;
int work(int m)
{
    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 work2(int len,char 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 get_next()
{
  nextt[0]=0;
  for(int i=1;i<len;++i){
    int temp=nextt[i-1];
	while(temp&&str[temp]!=str[i])
		temp=nextt[temp-1];
	if(str[i]==str[temp])
		nextt[i]=temp+1;
	else
		nextt[i]=0;
  }
  int x=len-nextt[len-1];
  if(len%x==0)
  {
    int y=len/x;
    return y;
  }
  else
	  return 1;
}
int main(){
	while(~scanf("%s",str)){
	  len=strlen(str);
	  int x=get_next();
	  int y=work(len);
	  int z=work2(len,str);
	  printf("%d %d %d %d\n",y+1,x,z+1,x);
	}
  return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: