【poj2406】 Power Strings

时间:2022-04-07 23:29:40

http://poj.org/problem?id=2406 (题目链接)

题意

  给定一个字符串 L,已知这个字符串是由某个字符串 S 重复 R 次而得到的, 求 R 的最大值。

Solution

  后缀数组论文题,然而nlogn的倍增竟然TLE了,那给3s是什么意思→_→

  做法比较简单,穷举字符串 S 的长度 k,然后判断是否满足。判断的时候,先看字符串 L 的长度能否被 k 整除,再看 suffix(1)和 suffix(k+1)的最长公共前缀是否等于 n-k。在询问最长公共前缀的时候,suffix(1)是固定的,所以 RMQ 问题没有必要做所有的预处理,只需求出 height 数组中的每一个数到 height[rank[1]]之间的最小值即可。整个做法的时间复杂度为 O(n)。

  这是论文里面的后缀数组做法,而我们用KMP就是从后往前算。

代码

// poj2406
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 1<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=1000010;
int next[maxn],n;
char s[maxn]; void calnext() {
next[1]=0;
for (int i=2,j=0;i<=n;i++) {
while (j && s[i]!=s[j+1]) j=next[j];
if (s[i]==s[j+1]) j++;
next[i]=j;
}
}
int main() {
while (scanf("%s",s+1)!=EOF) {
if (s[1]=='.') break;
n=strlen(s+1);
calnext();
for (int i=next[n];i>=0;i=next[i])
if (n%(n-i)==0) {printf("%d\n",n/(n-i));break;}
}
return 0;
}