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

来源:互联网 发布:哈车钥匙淘宝图片 编辑:程序博客网 时间:2024/05/21 18:37

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

求字典序最小最大直接最小最大表示法。出现次数的话,如果该字符串能多次出现一个同构串,那么这个字符串的循环节要大于1,不然就只能出现一次,所以用kmp求一下循环节就行了

#include <iostream>#include <string.h>#include <cstdio>using namespace std;const int N=1000010;int len,nextt[N];char str[N];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;elsenextt[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;}

0 0
原创粉丝点击