北大1961题

来源:互联网 发布:生死狙击刷枪刷枪软件 编辑:程序博客网 时间:2024/04/30 12:53

题目连接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1961

 

1,KMP算法本质是个迭代算法,最神奇的地方在于next函数。

2,其中next[j] = k代表的意思是如果pad与某个串匹配的过程中在第j位失配,下一次应该保持主串指针不动,让pad在指针k处的值代替原先的在指针i处的值开始继续比较。这个主串当然可以是与pad相同的串。形式化的说明就是:p0 p1……pk-1 = pj-k+1 pj-k+2 ……pj-1,且不存在k`>k满足上式。

3,从2的说明中经过一个不太容易理解(多看两边就能明白的)的求取next的迭代过程,迭代方程如下:

next[0] = -1

next[i+1] = next[i] + 1(p next[i] == pi)

next[i+1] = next[i`] + 1(p next[i`] == pi)

说明:在求pad的next函数时实际将pad的最后的/n也当做了一个字符。

4,换个角度去解释2中的next[i] = k,能得到pad的一些性质,next[i] = k 表示在pad中第i个位置失配时,应该将pad右移直到第k位取代第i位与母串当前指针处的字符进行比较。此时如果把移出的串作为一个整体,其长度设为slen,pad的长度设为tlen,如果tlen - slen能被slen整除表明移出的串是个最小基本串,整个pad是连续tlen/slen个基本串的组合,如果tlen - slen不能被slen整除那么剩余的串是个特殊前缀,之所以特殊是因为末尾有一个同样长度的串和他相等,并且这个长度是最大的。

5,这个题目实质就是要求一个串中是否由多个基本串构成如果有求出基本串的重复次数,只不过这个题稍微作了一些变化,给定一个串让求其前缀基本串重复次数大于1的情况,循环不就行了吗

 

#include <iostream>
using namespace std;

#define MAX 1000000

 

char str[MAX+1];
int len;
int next[MAX+1];


int main()
{
 freopen("in.txt","r",stdin);

 int i,j,t,c;
 c = 1;
 while(cin >> len && len)
 {
  cin >> str;
  
  next[0] = j = -1;
  i = 0;
  while(i < len)
  {
   if(j == -1 || str[i] == str[j])
   {
    ++i,++j;
    next[i] = j;//实际会把/n也看做一个字符
   }
   else
    j = next[j];
  }
  
  printf("Test case #%d/n",c++);
  for(i = 2;i <= len;++i)
  {
   t = i - next[i];
   if(i % t == 0 && i / t > 1)
    printf("%d %d/n",i,i/t);
  }
  printf("/n");
 }
 return 0;
}