poj2406

15103812_cSEt.gif 15103812_CBQv.gif View Code

    
/*Poj2406题解:
if (len % (len - next[len]) == 0 ),则重复子串的长度为 len - next[len].
证明如下,next[len]表示到len为止,满足既是前缀子串又是后缀子串的最长长度,
如下图{a,c}
= {b,d}
若len
% (len – next[len]) == 0 ,则说明{ a ,b} 的长度可以被{a, d} 的长度整除,同样可以被{b,c}的长度整除。
而此时,由于{b,c}是{b,d}的前缀子串又是后缀子串且保持{a,b}的长度可以被{a,c}整除。
这样,{a,c}就相当于原来的{a,d},而{b,c}就相当于原来的{b,d},通过这样的划分主串在不断减小,同样保持了len
% (len - next[len]) == 0的性质,不断划分的最后结果就是最后一次划分为2个相当的前后子串即重复子串。
Kmp的精髓:用kmp每次求得的next值就是当前到i为止的前子串与后子串相等的长度。*/

// kmp算法
#include " iostream "
using namespace std;
char s[ 10000001 ];
int next[ 10000001 ];
int L;
int i,j;
void Index_kmp()
{
while (i < L) // kmp核心算法
{
if (j == 0 || s[i] == s[j]) // 继续比较后继字符
{ ++ i; ++ j; next[i] = j; }
else
j
= next[j]; // 串向右移动
}
}
int main()
{
while ( 1 )
{
scanf(
" %s " ,s);
if (s[ 0 ] == ' . ' ) break ;
L
= strlen(s);
i
= 1 ; j = 0 ; next[ 0 ] = 0 ;

Index_kmp();
if (L % (L - next[L]) == 0 ) printf( " %d\n " ,L / (L - next[L])); // 形成周期性
else printf( " 1\n " );
}
return 0 ;
}

转载于:https://my.oschina.net/garyun/blog/602934

猜你喜欢

转载自blog.csdn.net/weixin_34309543/article/details/91774280
今日推荐