Given string of no more than 5, find the longest common substring
The total length of not more than 1w
Several serially connected together to the intermediate separated by different characters
After obtaining height, half answer is k, find the number of each period of continuous and k is not less than the height of the array, which is determined by the prefix, and each contains a sub-string from the string
$ O (nlogn) $
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 10000 + 10; int n, m; char s[maxn]; int sa[maxn], rank[maxn], height[maxn]; int tax[maxn], tp[maxn]; inline void tsort(){ for(int i = 1; i <= m; i++) tax[i] = 0; for(int i = 1; i <= n; i++) tax[rank[i]]++; for(int i = 2; i <= m; i++) tax[i] += tax[i - 1]; for(int i = n; i; i--) sa[tax[rank[tp[i]]]--] = tp[i]; } inline bool cmp(int *arr, int l, int r, int k){ return arr[l] == arr[r] && arr[l + k] == arr[r + k]; } void suffix_sort(){ m = 128; for(int i = 1; i <= n; i++) tp[i] = i; for(int i = 1; i <= n; i++) rank[i] = s[i]; tsort(); for(int k = 1, p = 0; p < n; k <<= 1, m = p){ p = k; for(int i = 1; i <= k; i++) tp[i] = n - k + i; for(int i = 1; i <= n; i++) if(sa[i] > k) tp[++p] = sa[i] - k; tsort(); swap(rank, tp); p = rank[sa[1]] = 1; for(int i = 2; i <= n; i++) rank[sa[i]] = cmp(tp, sa[i - 1], sa[i], k) ? p : ++p; } for(int i = 1, j, k = 0; i <= n; height[rank[i++]] = k) for(k ? k-- : 0, j = sa[rank[i] - 1]; s[j + k] == s[i + k]; k++); } int L[10], R[10], sum[10][maxn] = {0}; char temp[] = {'!', '@', '#', '$', 0}; int q[maxn], qcnt; int main(){ int N; scanf("%d", &N); n = 0; for(int i = 0; i < N; i++){ L[i] = n + 1; scanf("%s", s + 1 + n); n += strlen(s + 1 + n); R[i] = n; s[++n] = temp[i]; } s[n--] = 0; suffix_sort(); for(int i = 0; i < N; i++){ for(int j = L[i]; j <= R[i]; j++) sum[i][rank[j]]++; for(int j = 1; j <= n; j++) sum[i][j] += sum[i][j - 1]; } int l = 1, r = maxn, mid, ans = 0; for(int i = 0; i < N; i++) r = min(r, R[i] - L[i] + 1); bool flag; while(l <= r){ mid = l + r >> 1; qcnt = 0; for(int i = 1; i <= n; i++){ if(height[i] < mid) q[++qcnt] = i; } for(int i = 2; i <= qcnt; i++){ flag = true; for(int j = 0; j < N; j++) flag &= sum[j][q[i] - 1] - sum[j][q[i - 1] - 1] > 0; if(flag) break; } if(flag){ ans = mid; l = mid + 1; } else r = mid - 1; } printf("%d\n", ans); return 0; }