• hdu4333 扩展KMP


    慢慢研究可以发现,可以用扩展kmp来求。由于扩展kmp的next[]只有一部分,当前位子前面那部分和母串的后部分,所以可以将字符串复制接在后面一次。

    先求如果next[]>0&&next[]!=len,那么只要考虑后面那位的大小比较。如果next[]>=len 那就是相同。如果next[]==0,就是没有相同的,直接比较开头。

    这样做还是会超时,我tle无数发。

    还要去掉重复的部分,题目要求不同的。所以求出循环部分,只要考虑一部分即可。

        //扩展kmp求最小循环节
        int kk;  // kk保存最短循环节  
        for(i=1; i<=len; ++i)
        {  
            if(i+next[i]>=len)
            {  
                kk = len%i ? len : i;  
                break;  
            }  
        }  
    #include<stdio.h>
    #include<string.h>
    #define maxn 100010
    char s[maxn],ss[maxn*2];
    int next[maxn*2],n[maxn];
    void getnext()
    {
        int i,j,len=strlen(ss),k;
        next[0]=len;
        i=0;
        while(i<len-1&&ss[i]==ss[i+1])
            i++;
        next[1]=i;
        int a=1;
        for(k=2;k<len;k++)
        {
            int p=a+next[a]-1;
            int l=next[k-a];
            if(k-1+l>=p)
            {
                int j=p-k+1>0?p-k+1:0;
                while(j+k<len&&ss[j+k]==ss[j])
                    j++;
                next[k]=j;
                a=k;
            }
            else next[k]=l;
        }
    }
    void Ekmp()
    {
        getnext();
        int i,j,len=strlen(s),k;
        int ansmin,ansequ,ansmax;
        ansmin=ansequ=ansmax=0;
        //扩展kmp求最小循环节
        int kk;  // kk保存最短循环节  
        for(i=1; i<=len; ++i)
        {  
            if(i+next[i]>=len)
            {  
                kk = len%i ? len : i;  
                break;  
            }  
        }  
        for(i=0;i<kk;i++)
        {
            if(next[i]==0)
            {
                if(ss[i]>ss[0])
                    ansmax++;
                else ansmin++;
            }
            else if(next[i]>=len)
            {
                ansequ++;
            }
            else 
            {
                if(ss[next[i]+i]>ss[next[i]])
                {
                    ansmax++;
                }
                else ansmin++;
            }
        }
        printf("%d %d %d
    ",ansmin,ansequ,ansmax);
    }
    int main()
    {
        int i,j,t,ff=0,len;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%s",s);
            len=strlen(s);
            int k=0;
            for(i=0;i<len;i++)
                ss[k++]=s[i];
            for(i=0;i<len;i++)
                ss[k++]=s[i];
            ss[k]='';
            printf("Case %d: ",++ff);
            Ekmp();
        }
    }
  • 相关阅读:
    如何实现parseFloat保留小数点后2位
    C#正则表达式整理备忘
    HRESULT:0x80070057 (E_INVALIDARG)的异常的解决方案
    c# using的几种用法
    QQ截图 有快捷键的,如Shift+S
    史上最深刻的黄段子
    文本框回车自动提交
    C#与ASP.NET中DateTime.Now函数详解
    ASP.NET页面生命周期
    .NET中HttpWebRequest详解
  • 原文地址:https://www.cnblogs.com/sweat123/p/4727691.html
Copyright © 2020-2023  润新知