POJ 2406 KMP

题意:给定一个字符串,如 str : ababab, 则 str = ab ^ 3, 输出3。 又如 abcd, 输出 1。
题解:next 函数的应用, 理解并记住。

#include <iostream>
using namespace std;

#define N 1000005

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

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

int main()
{
	while ( scanf("%s",str) )
	{
		if ( str[0] == '.' )
			break;
		int len = strlen(str);
		get_next( len );
		if ( len % ( len - next[len] ) == 0 ) /* 注意必须模等于0,否则像 aabaabaa 就输出 2 (正确应该输出1). */
		    printf("%d\n", len / ( len - next[len] ) );
		else
			printf("1\n");
	}
	return 0;
}

Discuss里面有人用如下的方法,暂时还没看懂。先贴出来。
  设字符串s长度为l(l不超过1000000),如果s形如u^k,则称s具有周期数k
 
 引理一
  设s具有周期数m,n,令h为m,n的最小公倍数,那么s具有周期数h
 
引理二
  对l进行素因子分解,那么不同的素数最多出现7个


引理三
  设l[0],l[1],...,l[r]为一个有限长的正整数数列,满足l[k+1]整除l[k](0<=k<=r-1),
l[0]=l,并且满足l[k+1]=l[k]的k最多不超过7个,
那么l[0]+l[1]+...+l[r]<=7*l,等号成立当且仅当r=6,l[0]=l[1]=...=l[6]
 
算法 
(1)对l进行素因子分解,得到 l=p[0]^t[0]*p[1]^t[1]*...*p[d]^t[d]
  其中p[0]<p[1]<...<p[d]为素数,t[k]为正整数(0<=k<=d)
 
(2)设置初值k:=0,T:=1,执行下面循环,直到k=d+1结束
 {
    如果t[k]>0且s具有周期数p[k]
    记s:=s'^p[k]
    令s:=s',T:=T*p[k]
    t[k]:=t[k]-1
    若条件不成立k:=k+1
 }
 T即为所求
 
 算法的正确性由引理一保证,根据引理一,s的所有可能的周期数都是最大周期数的约数,又由于最大周期数是l的约数,算法正确性得证。
使用最朴素的方法检查“s是否具有周期数p[k]”,复杂度与length(s)成正比,
 记为C*length(s),可以证明,该算法复杂度不超过7*C*l 
 如果每次执行判断“s是否具有周期数p[k]”时,记下当前的length(s),我们得到数列
 l[0],l[1],...,l[r],
 那么,算法的复杂度就是C*(l[0]+l[1]+...+l[r])。
 借助引理二,可以证明,这个数列满足引理三的条件,因此得到最大复杂度7*C*l。
 同时,我们还知道,最大复杂度在周期数是1的时候取得。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值