POJ 2406 Power Strings

题目大意:

        定义字符串的幂运算,a^n就是指字符串a和自身连接n此,如果n=0则结果为空字符串。

        现有多个测例(以单个字符'.'表示测例的结束),每个测例都会给出一个字符串s(长度为[1, 1000000]),对于每个每个测例求s=a^n中n的最大值。

题目链接

注释代码:

/*   
 * Problem ID : POJ 2406 Power Strings
 * Author     : Lirx.t.Una   
 * Language   : G++  
 * Run Time   : 79 ms   
 * Run Memory : 5272 KB   
*/ 

#pragma G++ optimize("O2")

#include <string.h>
#include <stdio.h>

//即求简单周期
//可以利用next数组先求的最小循环节:
  //即s[ len-next[len] ~ len ]之间的字符串是s的一个子串
  //同时也可以利用该子串反复自身连接构成s(不一定是刚好能够构成s)
    //也可能是自身连接m次后再连接该子串的一部分刚好可以构成s
  //此子串就是s的循环节,并且是最短的,因此称为最小循环节
//这道题中需要求s的最小周期子串,如果s的长度能整除最小循环节的长度
  //则最小循环节的长度就是最小周期子串
  //如果不能整除就以为着s不存在周期子串,因此周期子串就是只有s本身了

#define	MAXLEN		1000002

char	s[MAXLEN];
int		nxt[MAXLEN];

int
bd_nxt(int len) {
	
	int		i, j;
	int		d;
	
	nxt[1] = 0;
	for ( j = 0, i = 2; i <= len; i++ ) {
		
		while ( j > 0 && s[j + 1] != s[i] )
			j = nxt[j];
		
		if ( s[j + 1] == s[i] )
			j++;
		
		nxt[i] = j;
	}
	
	d = len - nxt[len];//最小循环节的长度
	
	if ( !( len % d ) )//如果能整除则最小循环节就是最小周期子串
		//直接输出有多少个就行了
		return len / d;
	
	return 1;//否则s的周期子串就只有s本身了,直接输出1就行了
}

int
main() {
	
	int		len;
	
	while ( scanf("%s", s + 1), s[1] != '.' ) {
		
		len = strlen(s + 1);
		printf("%d\n", bd_nxt(len));
	}
	
	return 0;
}

无注释代码:

#pragma G++ optimize("O2")

#include <string.h>
#include <stdio.h>

#define	MAXLEN		1000002

char	s[MAXLEN];
int		nxt[MAXLEN];

int
bd_nxt(int len) {

	int		i, j;
	int		d;

	nxt[1] = 0;
	for ( j = 0, i = 2; i <= len; i++ ) {

		while ( j > 0 && s[j + 1] != s[i] )
			j = nxt[j];

		if ( s[j + 1] == s[i] )
			j++;

		nxt[i] = j;
	}

	d = len - nxt[len];

	if ( !( len % d ) )
		return len / d;

	return 1;
}

int
main() {

	int		len;

	while ( scanf("%s", s + 1), s[1] != '.' ) {
	
		len = strlen(s + 1);
		printf("%d\n", bd_nxt(len));
	}

	return 0;
}

单词解释:

concatenation:n, 串联,连接

power:n, 乘方,幂

multiplication:n, 乘法

exponentiation:n, 乘方,取幂运算

printable:adj, 可打印的,可出版的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值