這個題目是後綴數組專題裏面的一道題目。結果就是照着後綴數組的思路寫的果然超時了。結果上網一搜才發現kmp也能做,真是太死板了,做題。
思路:對於一個串如果它是某個串的重複得到的,那麼當前串的某個後綴串suff(i)與這串的公共前綴剛好就是那個後綴串suff(i),並且串長能整除i那麼這個串就是長度爲i的重複串。
AC代碼:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define Max_N (1000000 + 100)
int next1[Max_N];
void kmp_pre(char x[], int m, int next1[])
{
int i, j;
j = next1[0] = -1;
i = 0;
while (i < m)
{
while(-1 != j && x[i] != x[j]) j = next1[j];
next1[++i] = ++j;
}
}
char buf[Max_N];
int main()
{
while (true) {
scanf("%s", buf);
if (buf[0] == '.') return 0;
kmp_pre(buf, strlen(buf), next1);
int len = strlen(buf);
int ans = 0;
if (len % (len - next1[len]) == 0) ans = len / (len - next1[len]);
else ans = 1;
cout << ans << endl;
}
}
後綴超時代碼:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define Max_N (1000000 + 100)
#define INF 0x3f3f3f3f
int n;
int k;
int a[Max_N];
int rank1[Max_N];
int tmp[Max_N];
bool compare_sa(int i, int j)
{
if(rank1[i] != rank1[j]) return rank1[i] < rank1[j];
else {
int ri = i + k <= n ? rank1[i + k] : -1;
int rj = j + k <= n ? rank1[j + k] : -1;
return ri < rj;
}
}
void construct_sa(int buf[], int s, int sa[])
{
int len = s;
for (int i = 0; i <= len; i++) {
sa[i] = i;
rank1[i] = i < len ? buf[i] : -1;
}
for ( k = 1; k <= len; k *= 2) {
sort(sa, sa + len +1, compare_sa);
tmp[sa[0]] = 0;
for (int i = 1; i <= len; i++) {
tmp[sa[i]] = tmp[sa[i-1]] + (compare_sa(sa[i-1], sa[i]) ? 1 : 0);
}
for (int i = 0; i <= len; i++) {
rank1[i] = tmp[i];
}
}
}
void construct_lcp(int buf[], int len, int *sa, int *lcp)
{
int h = 0;
lcp[0] = 0;
for (int i = 0; i < len; i++) {
int j = sa[rank1[i] - 1];
if (h > 0) h--;
for (; j + h < len && i + h < len; h++) {
if (buf[j+h] != buf[i+h]) break;
}
lcp[rank1[i] - 1] = h;
}
}
int sa[Max_N];
int lcp[Max_N];
char buf1[Max_N];
int min1[Max_N];
int main()
{
while (true) {
scanf("%s", buf1);
if(buf1[0] == '.') break;
n = strlen(buf1);
for (int i = 0; i < n; i++) {
a[i] = int(buf1[i]);
}
construct_sa(a, n, sa);
construct_lcp(a, n, sa, lcp);
min1[rank1[0]] = INF;
for (int i = rank1[0]; i < n-1; i++) {
min1[i+1] = min(lcp[i], min1[i]);
}
for (int i = rank1[0]-1; i >= 0; i--) {
min1[i] = min(lcp[i], min1[i+1]);
}
int ans = 1;
for (int i = 1; i < n; i++) {
//cout << min1[rank1[i]] << endl;
if (min1[rank1[i]] == n - i && n % i == 0) {
ans = max(ans, n/i);
}
}
cout << ans << endl;
}
return 0;
}