题目大意:
定义字符串的幂运算,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, 可打印的,可出版的