• hdu 4333(扩展kmp)


    题意:就是给你一个数字,然后把最后一个数字放到最前面去,经过几次变换后又回到原数字,问在这些数字中,比原数字小的,相等的,大的分别有多少个。比如341-->134-->413-->341,所以和原数字相比,比原数字小的有一个,相等的有一个,大的有一个。

    分析:经过观察,其实就是求每一位的后缀与自身的最长公共前缀,这个显然可以用扩展kmp处理,但是开始的时候我超时了,后来在网上看到别人把这个串后面再接上本身,以它为主串,然后以自身为模板串进行扩展kmp,这样处理把时间复杂度降到了线性的,最后要注意的一个问题就是如何避免重复了,我们可以用普通的kmp求出此串的最小循环节,如果构成完整的循环,那么我们要算的就是循环节长度的情况了!

    代码实现:

    #include<stdio.h>
    #include<string.h>
    char S[201000],T[100500];
    int next[200500],extend[200500],len,node;
    
    void get_node()
    {
        int i=0,j=-1;
        next[0]=-1;
        while(i<len)
        {
            if(j==-1||T[i]==T[j])
            {
                i++;j++;
                next[i]=j;
            }
            else
             j=next[j];
        }
        node=len-next[len];
    }
    
    void get_next()
    {
        int a,p,k,j,len;
        int L;
        len=strlen(T);
        next[0]=len;
        a=0;
        while(a<len-1&&T[a]==T[a+1])
            a++;
        next[1]=a;
        a=1;
        for(k=2;k<len;k++)
        {
            p=a+next[a]-1;
            L=next[k-a];
            if(k-1+L>=p)
            {
                j=p-k+1>0?p-k+1:0;
                while(j+k<len&&T[j+k]==T[j])
                    j++;
                next[k]=j;
                a=k;
            }
            else
                next[k]=L;
        }
    }
    
    void get_extend()
    {
        get_next();
        int a,p,L,k,j,slen,tlen,len;
        slen=strlen(S);tlen=strlen(T);
        len=slen>tlen?tlen:slen;
        a=0;
        while(a<len&&S[a]==T[a])
            a++;
        extend[0]=a;
        a=0;
        for(k=1;k<slen;k++)
        {
            p=a+extend[a]-1;
            L=next[k-a];
            if(k-1+L>=p)
            {
                j=p-k+1>0?p-k+1:0;
                while(j+k<slen&&j<tlen&&S[j+k]==T[j])
                    j++;
                extend[k]=j;
                a=k;
            }
            else
                extend[k]=L;
        }
    }
    
    void solve()
    {
        int i,num1=0,num2=0,num3=0,flag;
        if(len%node!=0)
         node=len;
        for(i=0;i<node;i++)
        {
            if(extend[i]>=len)
             num2++;
            else if(S[extend[i]]>S[i+extend[i]])
             num1++;
            else if(S[extend[i]]<S[i+extend[i]])
             num3++;
        }
        printf("%d %d %d
    ",num1,num2,num3);
    }
    
    int main()
    {
        int t,i;
        scanf("%d",&t);
        getchar();
        for(i=1;i<=t;i++)
        {
            scanf("%s",T);
            strcpy(S,T);
            strcat(S,T);
            len=strlen(T);
            get_node();
            get_next();
            get_extend();
            printf("Case %d: ",i);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    parse_str — 将字符串解析成多个变量
    HTTP 协议入门
    Ruby自动文档工具 RDoc 3.3 发布 狼人:
    用好IE9浏览器必须要知道的九件事 狼人:
    微软缘何认为VB与C#需要异步语法 狼人:
    微软资深软件工程师:阅读代码真的很难 狼人:
    20款Web应用:可以替代桌面软件 狼人:
    互联网公司完善商业模式需完成七件事情 狼人:
    改良程序需要的11个技巧 狼人:
    开源网站建设工具Drupal 7发布 狼人:
  • 原文地址:https://www.cnblogs.com/jiangjing/p/3318532.html
Copyright © 2020-2023  润新知