HDU 4333 扩展KMP

点击打开链接

题意:一个数字,依次将第一位放到最后一位,问小于本身的数的个数及等于本身的个数和大于本身的个数,但是要注意重复的不再计算

思路:用扩展KMP我们可以处理,先将串复制到后面一次,然后求扩展KMP,那么我们如何比较呢,如果extand[i]的值大于串的长度len,说明我以i为开头的串和原串的匹配大于len,也就说明这个串和原串相等,接下来就是另外两种情况,若extand[i]匹配到了第三位,那么久比较原串的第三位和以i开始的第三位即可,比较过后,处理重复的串,用KMP即可处理,如果串是一个以长度为len1的子串重复得来,那么最后结果便全部除以len1,画一下就一目了然了

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=200010;
int Next[maxn],extand[maxn];
char T[maxn];
void makenext(int m){
    int i=0,j=-1;
    Next[i]=-1;
    while(i<m){
        if(j==-1||T[i]==T[j])
            Next[++i]=++j;
        else j=Next[j];
    }
}
void GetNext(const char *T){
     int len=strlen(T),a=0;
     extand[0]=len;
     while(a<len-1&&T[a]==T[a+1]) a++;
     extand[1]=a;
     a=1;
     for(int k=2;k<len;k++){
         int p=a+extand[a]-1,L=extand[k-a];
         if((k-1)+L>=p){
             int j=(p-k+1)>0? (p-k+1):0;
             while(k+j<len&&T[k+j]==T[j]) j++;
             extand[k]=j;
             a=k;
         }
         else extand[k]=L;
     }
}
int main(){
    int TT,t=1;
    scanf("%d",&TT);
    while(TT--){
        scanf("%s",T);
        int len=strlen(T);
        makenext(len);
        int k=len-Next[len];
        int tt;
        if(len%k==0) tt=len/k;
        else tt=1;
        for(int i=0;i<len;i++) T[len+i]=T[i];
        GetNext(T);
        int L=0,E=0,G=0;
        for(int i=0;i<len;i++){
            if(extand[i]>=len) E++;
            else if(T[extand[i]]>T[i+extand[i]]) L++;
            else if(T[extand[i]]<T[i+extand[i]]) G++;
        }
        printf("Case %d: %d %d %d\n",t++,L/tt,E/tt,G/tt);
    }
    return 0;
}

你可能感兴趣的:(数据结构,KMP,ACM,扩展,HDU)