HDU 4333 扩展KMP

来源:互联网 发布:打印票据软件 编辑:程序博客网 时间:2024/06/03 21:32

点击打开链接

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

思路:用扩展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;}

0 0
原创粉丝点击