hdu1358 最小循环节,最大循环次数 KMP

题意:
      给你一个字符串,让你找到一些字符串,这个字符串是从第一个字母开始的,并且他可以分成1个一上循环子结构够成的,比如 abcabcabc  那么当前的这个串就是三个abc构成的,他的AK值就是3,对于输出的答案中就会包含当前这个状态,表示为9 3。


思路:
      就像最小路径覆盖是二分匹配的一个景点应用一样,这种循环节的也是KMP的一个应用,结论是 
当 i % (i - next) == 0时,如果 i/(i - next[i]) > 1就输出 i ,i/(i-next[i]);

我对next[i]的理解是,next[i]保存的是当i匹配失败的时候,尽可能的可以不往前跑的那个坐标,也可以说找两个相同的字符串字符串,一个是以失配点前一个点为终点,另一个是以第一个点为起点,这两个串可以交叉但不可以完全相同,最长的这个串的长度的下一个就是匹配失败后可以直接匹配的点,也就是 比如1231231234 假如匹配到4的时候失配了,那么就直接退到123123的后面而不是退到起始点,这样就节省了没必要的比较。


#include<stdio.h>

#define N 1000000 + 100

char str[N];
int next[N];

void get_next(int m)
{
   int j ,k;
   j = 0 ,k = -1;
   next[0] = -1;
   while(j < m)
   {
      if(k == -1 || str[j] == str[k])
      next[++j] = ++k;
      else
      k = next[k];
   }
   return ;
}

int main ()
{
   int n ,i ,cas = 1;
   while(~scanf("%d" ,&n) && n)
   {
      scanf("%s" ,str);
      get_next(n);
      printf("Test case #%d
" ,cas ++);
      for(i = 2 ;i <= n ;i ++)
      {
         if(i % (i - next[i]))
         continue;
         int tmp = i / (i - next[i]);
         if(tmp > 1)
         printf("%d %d
" ,i ,tmp);
      }
      printf("
");
   }
   return 0;
}
      


原文地址:https://www.cnblogs.com/csnd/p/12063114.html