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-i));break;} } return 0; }