• hdu 1358 kmp 求前缀有几个循环


    [1,2...,m] 模板的前缀Pi 的循环节为  clc = i-next[i]   

    i % clc == 0 && i != clc  则表示前缀中有 k = i / clc 个循环

    完全是参考代码模板:

    代码如下:

    #include<iostream>
    #include<stdio.h>
    #include<string>
    #include<string.h>
    #define N 1000005
    using namespace std;
    char P[N];
    int m;
    int next[N];
     void Prefix_Func()
     {
         int i,k;
         k=0;
         next[1]=0;
         for(i=2;i<=m;i++)
         {
            while(k>0 && P[k+1]!= P[i])
                k=next[k];
            if(P[k+1] == P[i])
                k++;
            next[i]=k;
         }
     }
    int main()
    {
        int t=1,clc;
    
        while(scanf("%d",&m) && m)
        {
            scanf("%s",P+1);
            Prefix_Func();
            cout<<"Test case #"<<t++<<endl;
            for(int i=2;i<=m;i++)
            {
                clc=i-next[i];
                if(i%clc == 0 && i!=clc)
                    cout<<i<<" "<<i/clc<<endl;
            }
            cout<<endl;
        }
        return 0 ;
    }

    poj 2406

    求字符串有几个周期

    kmp next函数 kmp的周期问题,深入了解kmp中next的原理

     

    -----------------------

    -----------------------

    k    m        x      j       i

    k=0.

    由上,next【i】=j,两段红色的字符串相等(两个字符串完全相等),s[k....j]==s[m....i]

    设s[x...j]=s[j....i](xj=ji)

    则可得,以下简写字符串表达方式

    kj=kx+xj;

    mi=mj+ji;

    因为xj=ji,所以kx=mj,如下图所示

    -------------

          -------------

     k   m        x     j   

    看到了没,此时又重复上面的模型了,kx=mj,所以可以一直这样递推下去

    所以可以推出一个重要的性质len-next[i]为此字符串的最小循环节(i为字符串的结尾),另外如果len%(len-next[i])==0,此字符串的最小周期就为len/(len-next[i]);否则,最小周期为1,。

    代码如下:

    const int Max_N = 1000005;
    // 求后缀数组, 求循环节时只能模式下标从1开始,
    int next[Max_N];
    char P[Max_N];
    int m;
    void prefix(){
        int i, k=0;
        next[1]=0;
        for(i =2 ; i<= m ; i++){
            while(k>0 && P[k+1] != P[i])
                k=next[k];
            if(P[k+1] == P[i]) k++;
            next[i] = k;
        }
    }
    int main(){
        while(scanf("%s",P+1) )
        {
            if(P[1] == '.')  break;
            m= strlen(P+1);
            prefix();
            if(m % (m - next[m]) ==0)  printf("%d
    ", m / (m - next[m]) );
            else   printf("1
    ");
        }
    }

     另一份代码为:

    int next[1000005];
    
    int kmp_next(char *pat)
    {
        int i=0,j=-1;
        next[0]=-1;
        int len = strlen(pat);
        while(i<len)
        {
            if(j==-1||pat[i]==pat[j])
                next[++i]=++j;
            else
                j=next[j];
        }
        i=len - j;
        if(len%i==0)
            return len / i;
        else
            return 1;
    }
    
    int main()
    {
        char s[1000005];
        while(scanf("%s",s)!=EOF)
        {
            if(s[0]=='.')
                break;
            printf("%d
    ",kmp_next(s));
        }
        return 0;
    }
  • 相关阅读:
    利用Spring MVC 上传图片文件
    HdU 4046 Panda 段树
    unity3D的FingerGestures小工具
    深入了解java同步、锁紧机构
    _00021 尼娜抹微笑伊拉克_谁的的最离奇的异常第二阶段 Jedis pool.returnResource(jedis)
    【从翻译mos文章】正在实施的获取job的 session id
    找呀志_通过开源框架引AsyncHttpClient上传文件
    [LeetCode]Count and Say
    使用Intent启动组件
    cpe移植framework后,。解决问题的现有数据库
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3571521.html
Copyright © 2020-2023  润新知