Kmp算法-未完

一:Kmp算法

概要:

Kmp算法中nxt数组为重要组成部分,nxt数组所存的内容为:next[i]表示前i个字符组成的子串的最长相同前缀和后缀的长度,要注意应用中提出的nxt[i]变化(方便在匹配两个字符串时候跳动减少时间复杂度)

nxt数组模板:

以i=1为起点的字符串进行处理

void get_nxt()
{
    nxt[0]=nxt[1]=0;
    for(int i=2,j=0;i<=m;++i){
        while(j&&str[j+1]!=str[i]) j=nxt[j];//交换后从头再次匹配前缀和后缀
        if(str[j+1]==str[i])
            ++j;
        nxt[i]=j;
    }
}

应用:

 

    求前缀串子串的周期和子串的长度

    求前缀串在原串中能匹配的次数

 

1.POJ-1961  Period

题意:

  求字符串的每个前缀串是否有周期,和周期的具体值

 

  若此字符串前缀和后缀相同的情况则会发生nxt[i]连续加的情况 

  所以求前缀传是否为周期串是会出现叠加的情况,根据叠加情况此时的i-nxt[i]即为所求串的长度,若%为0则满足条件,只需要仔细想想就会发现满足%为0的就是所求的len!因为nex[i]是在前缀后缀相同的情况下会叠加

int main()
{
    int cnt=1;
    while(~scanf("%d",&m)&&m){
        getchar();scanf("%s",str+1);
        get_next();
         printf("Test case #%d\n",cnt++);
        for(int i=2;i<=m;++i){
            int len=i-Next[i];
            if(i%len==0&&Next[i])
                printf("%d %d\n",i,i/len);
        }
        printf("\n");

    }
}

 

 

2.HDU-3336 Count the string
题意:
  求一个串的前缀在这个串中有多少个匹配
  此题网上很多人的解法都是错误的会有aaa答案是5的情况但其实aaa的答案是6
  aaa-a*3-aa*2-aaa
  dp[i]=dp[nxt[i]]+1的理解
  dp[i]代表的是以第i个字符结尾的前缀串所具有的匹配个数,这个个数就是他所匹配的前缀中有的+上他自己的一个就是他的
  比如说dp[8]=dp[3]+1,那么这个以8结尾的前缀串中含有一个长度为3的前缀后缀相同,则他这个后缀匹配个数为前缀所能匹配的相同+1,微小状态的叠加

int main()
{
    int t;scanf("%d",&t);
    while(t--){
        scanf("%d%s",&m,b+1);
        get_nxt();
        dp[0]=0;//相当于初始化了数组
        int ans=0;
        for(int i=1;i<=m;++i){
            dp[i]=dp[nxt[i]]+1;//dp
            dp[i]%=mod;
            ans=(ans+dp[i])%mod;
        }
        printf("%d\n",ans);

    }
}

 

 

 最后放两个学习Kmp时候看的博客

http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

https://www.cnblogs.com/SYCstudio/p/7194315.html

 

 

 

 

 

 

posted @ 2020-04-01 18:47  waryan  阅读(142)  评论(0编辑  收藏  举报