poj2406(kmp算法)

时间:2021-06-18 21:54:46
Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).

Input

Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.

Output

For each s you should print the largest n such that s = a^n for some string a.

Sample Input

abcd
aaaa
ababab
.

Sample Output

1
4
3

Hint

This problem has huge input, use scanf instead of cin to avoid time limit exceed.
简单的kmp算法next数组的运用,此博客是为了我以后的学习引以为戒!!!

大意:给出一个字符串 问它最多由多少相同的字串组成 (转载自https://www.cnblogs.com/zhanzhao/p/4761477.html)

如  abababab由4个ab组成

分析:

kmp中的next数组求最小循环节的应用

例如

ababab  next[6] = 4; 即

ababab

ababab

1~4位  与2~6位是相同的

那么前两位

就等于3、4位

3、4位就等于5、6位

……

所以 如果 能整除  也就循环到最后了

如果不能整除

就最后余下的几位不在循环内

例如

1212121

  1212121

最后剩余1不能等于循环节

难以置信我居然卡在这题三个小时,最后发现原因的我眼泪流下来,居然k的值设为-1就过了,一开始看到别人不同的代码还以为我算法思路错了,最终经过两个小时的研究(一次次模拟算法的运行QAQ)才发现算法思路一样,只是写法不同,只是我的代码在对于特殊数据时会卡死,顿时感觉要吐血,果然还是太菜了,打代码时不能分心,不能浮躁,不能一超时找不到问题就去百度,不能一看到别人代码不同就慌了神,怀疑自己对这个算法的学习产生了错误,果然还是要冷静啊,仔细看看自己的代码对于特殊数据是否会有bug,引以为戒引以为戒!

#include<stdio.h>
#include<string.h>
char str[1000005];
int next[1000005];
int main ()
{
  int i ,n;
  while(scanf("%s" ,str)!=EOF && str[0] != '.')
  {
    //printf("WWW\n");
    n = strlen(str);
    int k = -1;
    next[0] = -1;
    for(i=1;i<n;i++)
    {
      //printf("%d %d\n",i,k);
      while(k>-1&&str[k+1]!=str[i])
      {
        //printf("%d %c %c\n",k,str[k],str[i]);
        k=next[k];
      }
      if(str[k+1]==str[i])
      k++;
      next[i]=k;      

    }
    int t=next[n-1]+1;
    if (n % (n-t)==0) printf("%d\n", n / (n-t));
    else printf("%d\n", 1);
  }
    return 0;
}

此代码核心的另一种写法(大同小异)

    int k = -1;

    int j = 0;

    next[0] = -1; 
      while(j<n)
    {
      //printf("%d %d\n",i,k);
      if(k==-1||s[j] == s[k])

      {

        next[++j]=++k;  

      }

      else

      k=next[k];   

    }

我卡bug的代码

    n = strlen(str); //这代码咋一看没有错误,但是仔细观察后会发现当输入数据为aabbaa时这个代码会卡死,原因是当i=2时
    int k = 0; 
    next[0] = 0; 
    for(i=1;i<n;i++)
    {
      //printf("%d %d\n",i,k);
      while(k>0&&str[k]!=str[i])//这个while语句会陷入死循环
      {
        //printf("%d %c %c\n",k,str[k],str[i]);
        k=next[k];//k=next[k]=1,在这种情况下会一直执行这个while语句,睡完午觉后才突然发现。。。。,
      }
      if(str[k]==str[i])
      k++;
      next[i]=k;      

    }

总之,以后打代码不能总是只考虑到一种可能出错的方式,要看看自己的代码是否会卡在某些特殊数据上,如果遇到错误千万不能心急,首先要冷静下来,仔细看看自己的代码可能出错的地方,可能会发生错误的地方和数据,只有这样才能高效的找出问题的所在!!!