zoukankan      html  css  js  c++  java
  • HDU 4333 Revolving Digits (扩展KMP)

    题意:给你一个数,每次把这个数尾巴上的一个数字放到前面来,问如此循环一遍形成的新的(不重复)数字中,大于,等于,小于原数字的数各有多少个。

    比如样例:341->134->413->341,小于、等于、大于的各有1个。

    这个串后面接上它本身,作为主串,原串作为模式串。显然这题就是要求出主串每个后缀与模式串的最长公共前缀,直接套扩展KMP模板即可。

    因为形成的新的数字必须不重复,因此还需要用KMP的next函数求一下最短循环节。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int MAXN = 2001000;
    
    int next[MAXN],extand[MAXN];
    char S[MAXN],T[MAXN];
    int nextval[MAXN];
    int len;
    
    void KMPgetNext(char s[],int next[])
    {
        int length=len;
        int i=0,j=-1;
        next[0]=-1;
        while(i<length)
        {
            if(j==-1||s[i]==s[j])
            {
                ++i;
                ++j;
                next[i]=j;
            }
            else
                j=next[j];
        }
        return;
    }
    
    void GetNext(const char *T)
    {
        len=strlen(T);
        int a=0;
        next[0]=len;
        while(a<len-1 && T[a]==T[a+1]) a++;
        next[1]=a;
        a=1;
        for(int k=2; k<len; k++)
        {
            int p=a+next[a]-1,L=next[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++;
                next[k]=j;
                a=k;
            }
            else
                next[k]=L;
        }
    }
    
    void GetExtand(const char *S,const char *T)
    {
        GetNext(T);
        int slen=strlen(S),tlen=strlen(T),a=0;
        int MinLen = slen < tlen ? slen : tlen;
        while(a<MinLen && S[a]==T[a]) a++;
        extand[0]=a;
        a=0;
        for(int k=1; k<slen; k++)
        {
            int p=a+extand[a]-1, L=next[k-a];
            if( (k-1)+L >= p)
            {
                int j= (p-k+1) > 0 ? (p-k+1) : 0;
                while(k+j<slen && j<tlen && S[k+j]==T[j]) j++;
                extand[k]=j;
                a=k;
            }
            else
                extand[k]=L;
        }
    }
    
    int main()
    {
        int casN, cas = 0;
        scanf( "%d", &casN );
        while ( casN-- )
        {
            scanf( "%s", T );
            strcpy( S, T );
            strcat( S, T );
            GetExtand( S, T );
            KMPgetNext( T, nextval );
    
            int subL = ( len % ( len - nextval[len]) ) ? len : ( len - nextval[len] );
            //printf("%d
    ", subL );
            int L = 0, E = 0, G = 0;
            for ( int i = 0; i < subL; ++i )
            {
                if ( extand[i] >= len ) ++E;
                else if ( S[ extand[i] ] > S[ i + extand[i] ] ) ++L;
                else if ( S[ extand[i] ] < S[ i + extand[i] ] ) ++G;
            }
    
            printf("Case %d: %d %d %d
    ", ++cas, L, E, G );
        }
        return 0;
    }
  • 相关阅读:
    第十章 Ingress
    第九章 Service
    第八章 资源控制器
    第一章 Xshell5评估期已过问题
    第七章 yaml格式
    第六章 资源清单
    第五章 配置私有仓库Harbor
    第四章 K8s部署安装
    36 SpringBoot 在系统配置文件中动态加载配置
    Java 集合、数组 任意个数数字相加等于一个指定的数
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3350429.html
Copyright © 2011-2022 走看看