hdu 3374

最小表示+kmp

#include<iostream>
using namespace std;
const int maxn=2000005;
//最小表示+最大表示+KMP
//问题描述,求字典序最小的和字典序最大的位置,若多个取最左边的,并给出在这n个串中出现次数
//注意自身得情况,由于出始扩大了一倍,但自身只能算一次,这里要注意
char b[maxn];
char a[maxn];
int next[maxn];
int minshow(char *s)
{
    int i=0,j=1,k=0,n=strlen(s);
    while(i<n/2&&j<n/2&&k<n/2)
    {
          if(s[i+k]==s[j+k])k++;
          else
          {
               if(s[i+k]>s[j+k])i+=(k+1);
               else j+=(k+1);
               if(i==j)j++;
               k=0;
               }                   
          }
    return min(i,j);
    }
int maxshow(char *s)
{
    int i=0,j=1,k=0,n=strlen(s);
    while(i<n/2&&j<n/2&&k<n/2)
    {
          if(s[i+k]==s[j+k])k++;
          else
          {
               if(s[i+k]<s[j+k])i+=(k+1);
               else j+=(k+1);
               if(i==j)j++;
               k=0;
               }                   
          }
    return min(i,j);
    }
void slove(char *s)
{
    int i,j,len=strlen(s);
    next[0]=0;j=0;
    for(i=1;i<len;i++)
    {
        while(j>0&&s[j]!=s[i])j=next[j-1];
        if(s[j]==s[i])j++;
        next[i]=j;             
        }
    }   
int kmp(char *a,char *b)
{
    int i,j=0,lena=strlen(a),lenb=strlen(b),c=0;
    for(i=0;i<lenb;i++)
    {
        while(j>0&&a[j]!=b[i])j=next[j-1];
        if(a[j]==b[i])j++;
        if(j==lena){j=next[j-1];c++;}              
        }
    return c;   
    }   
int main()
{
    int i,j,k,n,mins,maxs,mint,maxt;
    while(gets(b))
    {
          n=strlen(b);
          for(i=0;i<n;i++)b[i+n]=b[i];
          b[n+n]=0;
          mins=minshow(b)+1;
          for(i=0;i<n;i++)a[i]=b[i+mins-1];
          a[n]=0;
          slove(a);
          mint=kmp(a,b+1);
         
          maxs=maxshow(b)+1;
          for(i=0;i<n;i++)a[i]=b[i+maxs-1];
          a[n]=0;
          slove(a);
          maxt=kmp(a,b+1);
          printf("%d %d %d %d\n",mins,mint,maxs,maxt);       
          }
    return 0;
    }

posted on 2011-08-10 10:29  宇宙吾心  阅读(352)  评论(0)    收藏  举报

导航