1. 程式人生 > >Power Strings POJ

Power Strings POJ

這個題目是字尾陣列專題裡面的一道題目。結果就是照著字尾陣列的思路寫的果然超時了。結果上網一搜才發現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; }