Given a string, the longest repeated substring that appears at least k times can overlap.
Analysis: Classic suffix array solution: divide the suffix into several groups. Here we need to determine whether there is a group of qualified suffixes (height [I]> = mid) not less than k. If yes, it exists.
K identical substrings meet the conditions, otherwise they do not exist
# Include <cstdio> # include <iostream> # include <cstring> # include <algorithm> using namespace std; # define N 22222 # define M 1111111 # define INF 0x7fffff/***** suffix array template *****/# define F (x) /3 + (x) % 3 = 1? 0: tb) // F (x) To find the starting position of suffix (x) of the original string in the new string # define G (x) <tb? (X) * 3 + 1 :( (x)-tb) * 3 + 2) // G (x) is the position of the new string suffix (x) in the original string, and F (x) are reciprocal operations int wa [N], wb [N], wv [N], WS [M]; int sa [N * 3]; // suffix smaller than I. The starting position is int rank1 [N] and height [N] in the source string. // rank the int r [N * 3] In the suffix arrangement with rank starting from I. // If the input is a string, used to calculate int c0 (int * r, int a, int B) {return r [a] = r [B] & r [a + 1] = r [B + 1] & r [a + 2] = r [B + 2];} int c12 (int k, int * r, int a, int B) {if (k = 2) return r [a] <r [B] | (r [a] = r [B] & c12 (1, r, a + 1, B + 1 )); Else return r [a] <r [B] | (r [a] = r [B] & wv [a + 1] <wv [B + 1]) ;} void sort (int * r, int * a, int * B, int n, int m) {int I; for (I = 0; I <n; I ++) wv [I] = r [a [I]; for (I = 0; I <m; I ++) WS [I] = 0; for (I = 0; I <n; I ++) WS [wv [I] ++; for (I = 1; I <m; I ++) WS [I] + = WS [I-1]; for (I = n-1; I> = 0; I --) B [-- WS [wv [I] = a [I]; return;} // Note: To facilitate recursive processing, the size of the r array and sa array is 3 * n void dc3 (int * r, int * sa, int n, int m) {// The rn array stores the new recursive string, and the san array is Sa int I, j, * rn = r + n, * san = sa + n, ta = 0, tb = (n + 1)/3, tbc = 0, p; r [n] = r [n + 1] = 0; for (I = 0; I <n; I ++) {if (I % 3! = 0) wa [tbc ++] = I; // tbc indicates the number of suffixes where the modulo 3 is 1 or 2 at the starting position} sort (r + 2, wa, wb, tbc, m); sort (r + 1, wb, wa, tbc, m); sort (r, wa, wb, tbc, m); for (p = 1, rn [F (wb [0])] = 0, I = 1; I <tbc; I ++) rn [F (wb [I])] = c0 (r, wb [I-1], wb [I])? P-1: p ++; if (p <tbc) dc3 (rn, san, tbc, p); else {for (I = 0; I <tbc; I ++) san [rn [I] = I ;}// sorts all suffixes where the starting position modulo 3 is equal to 0 for (I = 0; I <tbc; I ++) {if (san [I] <tb) wb [ta ++] = san [I] * 3;} if (n % 3 = 1) // n % 3 = 1, special processing of suffix (n-1) wb [ta ++] = n-1; sort (r, wb, wa, ta, m ); for (I = 0; I <tbc; I ++) wv [wb [I] = G (san [I])] = I; // merge the sorting results of all suffixes and save them in the sa array for (I = 0, j = 0, p = 0; I <ta & j <tbc; p ++) sa [p] = c12 (wb [j] % 3, r, wa [I], wb [j])? Wa [I ++]: wb [j ++]; for (; I <ta; p ++) sa [p] = wa [I ++]; (; j <tbc; p ++) sa [p] = wb [j ++]; return ;}// height [I] = suffix (sa [I-1]) the longest public prefix of suffix (sa [I]), that is, the longest public prefix of the two adjacent suffixes void calheight (int * r, int * sa, int n) {int I, j, k = 0; for (I = 1; I <= n; I ++) rank1 [sa [I] = I; for (I = 0; I <n; height [rank1 [I ++] = k) for (k? K --: 0, j = sa [rank1 [I]-1]; r [I + k] = r [j + k]; k ++ );} bool judge (int mid, int n, int k) {int cnt = 1; for (int I = 1; I <= n; I ++) {if (height [I] >=mid) {cnt ++;} else cnt = 1; if (cnt> = k) return true;} return false ;} int main () {int n, k; cin> n> k; for (int I = 0; I <n; I ++) {scanf ("% d", & r [I]); r [I] ++;} r [n] = 0; // minimum end dc3 (r, sa, n +); calheight (r, sa, n); int l = 1, r = n, mid; // enumerated length int ans = 0; while (l <= r) {mid = (l + r)> 1; if (judge (mid, n, k) {ans = mid; l = mid + 1 ;}else {r = mid-1 ;}}cout <ans <endl; return 0 ;} # include <cstdio> # include <iostream> # include <cstring> # include <algorithm> using namespace std; # define N 22222 # define M 1111111 # define INF 0x7fffff/***** suffix array template *****/# define F (x) /3 + (x) % 3 = 1? 0: tb) // F (x) To find the starting position of suffix (x) of the original string in the new string # define G (x) <tb? (X) * 3 + 1 :( (x)-tb) * 3 + 2) // G (x) is the position of the new string suffix (x) in the original string, and F (x) are reciprocal operations int wa [N], wb [N], wv [N], WS [M]; int sa [N * 3]; // suffix smaller than I. The starting position is int rank1 [N] and height [N] in the source string. // rank the int r [N * 3] In the suffix arrangement with rank starting from I. // If the input is a string, used to calculate int c0 (int * r, int a, int B) {return r [a] = r [B] & r [a + 1] = r [B + 1] & r [a + 2] = r [B + 2];} int c12 (int k, int * r, int a, int B) {if (k = 2) return r [a] <r [B] | (r [a] = r [B] & c12 (1, r, a + 1, B + 1); else Return r [a] <r [B] | (r [a] = r [B] & wv [a + 1] <wv [B + 1]);} void sort (int * r, int * a, int * B, int n, int m) {int I; for (I = 0; I <n; I ++) wv [I] = r [a [I]; for (I = 0; I <m; I ++) WS [I] = 0; for (I = 0; I <n; I ++) WS [wv [I] ++; for (I = 1; I <m; I ++) WS [I] + = WS [I-1]; for (I = n-1; I> = 0; I --) B [-- WS [wv [I] = a [I]; return;} // Note: To facilitate recursive processing, the size of the r array and sa array is 3 * nvoid dc3 (int * r, int * sa, int n, int m) {// The rn array stores the new recursive string, and the san array is the sa int of the new string. I, j, * rn = r + n, * san = sa + n, ta = 0, tb = (n + 1)/3, tbc = 0, p; r [n] = r [n + 1] = 0; for (I = 0; I <n; I ++) {if (I % 3! = 0) wa [tbc ++] = I; // tbc indicates the number of suffixes where the modulo 3 is 1 or 2 at the starting position} sort (r + 2, wa, wb, tbc, m); sort (r + 1, wb, wa, tbc, m); sort (r, wa, wb, tbc, m); for (p = 1, rn [F (wb [0])] = 0, I = 1; I <tbc; I ++) rn [F (wb [I])] = c0 (r, wb [I-1], wb [I])? P-1: p ++; if (p <tbc) dc3 (rn, san, tbc, p); else {for (I = 0; I <tbc; I ++) san [rn [I] = I ;}// sorts all suffixes where the starting position modulo 3 is equal to 0 for (I = 0; I <tbc; I ++) {if (san [I] <tb) wb [ta ++] = san [I] * 3;} if (n % 3 = 1) // n % 3 = 1, special processing of suffix (n-1) wb [ta ++] = n-1; sort (r, wb, wa, ta, m ); for (I = 0; I <tbc; I ++) wv [wb [I] = G (san [I])] = I; // merge the sorting results of all suffixes and save them in the sa array for (I = 0, j = 0, p = 0; I <ta & j <tbc; p ++) sa [p] = c12 (wb [j] % 3, r, wa [I], wb [j])? Wa [I ++]: wb [j ++]; for (; I <ta; p ++) sa [p] = wa [I ++]; (; j <tbc; p ++) sa [p] = wb [j ++]; return ;}// height [I] = suffix (sa [I-1]) the longest public prefix of suffix (sa [I]), that is, the longest public prefix of the two adjacent suffixes void calheight (int * r, int * sa, int n) {int I, j, k = 0; for (I = 1; I <= n; I ++) rank1 [sa [I] = I; for (I = 0; I <n; height [rank1 [I ++] = k) for (k? K --: 0, j = sa [rank1 [I]-1]; r [I + k] = r [j + k]; k ++ );} bool judge (int mid, int n, int k) {int cnt = 1; for (int I = 1; I <= n; I ++) {if (height [I] >=mid) {cnt ++;} else cnt = 1; if (cnt> = k) return true;} return false ;} int main () {int n, k; cin> n> k; for (int I = 0; I <n; I ++) {scanf ("% d", & r [I]); r [I] ++;} r [n] = 0; // minimum end dc3 (r, sa, n +); calheight (r, sa, n); int l = 1, r = n, mid; // enumerated length int ans = 0; while (l <= r) {mid = (l + r)> 1; if (judge (mid, n, k) {ans = mid; l = mid + 1 ;}else {r = mid-1 ;}}cout <ans <endl; return 0 ;}
Because m is too large and n is only 2 w, after simple discretization, the base sorting efficiency is improved, and the total efficiency is also improved.
# Include <cstdio> # include <iostream> # include <cstring> # include <algorithm> using namespace std; # define N 22222 # define INF 0x7FFFFFFF/***** suffix array template *****/# define F (x)/3 + (x) % 3 = 1? 0: tb) // F (x) To find the starting position of suffix (x) of the original string in the new string # define G (x) <tb? (X) * 3 + 1 :( (x)-tb) * 3 + 2) // G (x) is the position of the new string suffix (x) in the original string, and F (x) are reciprocal operations int wa [N], wb [N], wv [N], WS [N]; int sa [N * 3]; // suffix smaller than I. The starting position is int rank1 [N] and height [N] in the source string. // rank the int r [N * 3] In the suffix arrangement with rank starting from I. // If the input is a string, used to calculate int c0 (int * r, int a, int B) {return r [a] = r [B] & r [a + 1] = r [B + 1] & r [a + 2] = r [B + 2];} int c12 (int k, int * r, int a, int B) {if (k = 2) return r [a] <r [B] | (r [a] = r [B] & c12 (1, r, a + 1, B + 1 )); Else return r [a] <r [B] | (r [a] = r [B] & wv [a + 1] <wv [B + 1]) ;} void sort (int * r, int * a, int * B, int n, int m) {int I; for (I = 0; I <n; I ++) wv [I] = r [a [I]; for (I = 0; I <m; I ++) WS [I] = 0; for (I = 0; I <n; I ++) WS [wv [I] ++; for (I = 1; I <m; I ++) WS [I] + = WS [I-1]; for (I = n-1; I> = 0; I --) B [-- WS [wv [I] = a [I]; return;} // Note: To facilitate recursive processing, the size of the r array and sa array is 3 * n void dc3 (int * r, int * sa, int n, int m) {// The rn array stores the new recursive string, and the san array is Sa int I, j, * rn = r + n, * san = sa + n, ta = 0, tb = (n + 1)/3, tbc = 0, p; r [n] = r [n + 1] = 0; for (I = 0; I <n; I ++) {if (I % 3! = 0) wa [tbc ++] = I; // tbc indicates the number of suffixes where the modulo 3 is 1 or 2 at the starting position} sort (r + 2, wa, wb, tbc, m); sort (r + 1, wb, wa, tbc, m); sort (r, wa, wb, tbc, m); for (p = 1, rn [F (wb [0])] = 0, I = 1; I <tbc; I ++) rn [F (wb [I])] = c0 (r, wb [I-1], wb [I])? P-1: p ++; if (p <tbc) dc3 (rn, san, tbc, p); else {for (I = 0; I <tbc; I ++) san [rn [I] = I ;}// sorts all suffixes where the starting position modulo 3 is equal to 0 for (I = 0; I <tbc; I ++) {if (san [I] <tb) wb [ta ++] = san [I] * 3;} if (n % 3 = 1) // n % 3 = 1, special processing of suffix (n-1) wb [ta ++] = n-1; sort (r, wb, wa, ta, m ); for (I = 0; I <tbc; I ++) wv [wb [I] = G (san [I])] = I; // merge the sorting results of all suffixes and save them in the sa array for (I = 0, j = 0, p = 0; I <ta & j <tbc; p ++) sa [p] = c12 (wb [j] % 3, r, wa [I], wb [j])? Wa [I ++]: wb [j ++]; for (; I <ta; p ++) sa [p] = wa [I ++]; (; j <tbc; p ++) sa [p] = wb [j ++]; return ;}// height [I] = suffix (sa [I-1]) the longest public prefix of suffix (sa [I]), that is, the longest public prefix of the two adjacent suffixes void calheight (int * r, int * sa, int n) {int I, j, k = 0; for (I = 1; I <= n; I ++) rank1 [sa [I] = I; for (I = 0; I <n; height [rank1 [I ++] = k) for (k? K --: 0, j = sa [rank1 [I]-1]; r [I + k] = r [j + k]; k ++ );} bool judge (int mid, int n, int k) {int cnt = 1; for (int I = 1; I <= n; I ++) {if (height [I] >=mid) {cnt ++;} else cnt = 1; if (cnt> = k) return true;} return false ;} int xx [N], x [N]; int search (int v, int m) {int l = 0, r = m-1; while (l <= r) {int mid = (l + r)/2; if (x [mid] = v) return mid; if (v <x [mid]) r = mid-1; else l = mid + 1;} return-1;} int m Ain () {int n, k; cin> n> k; for (int I = 0; I <n; I ++) {scanf ("% d ", & x [I]); xx [I] = x [I];} int m = 1; for (int I = 1; I <n; I ++) {// discretization deduplication if (x [I]! = X [I-1]) x [m ++] = x [I];} sort (x, x + m); for (int I = 0; I <n; I ++) r [I] = search (xx [I], m) + 1; // for (int I = 0; I <n; I ++) cout <r [I] <''; // cout <endl; r [n] = 0; // minimum end dc3 (r, sa, n +); calheight (r, sa, n); int l = 1, r = n, mid; // enumeration length int ans = 0; while (l <= r) {mid = (l + r)> 1; if (judge (mid, n, k) {ans = mid; l = mid + 1 ;}else {r = mid-1 ;}}cout <ans <endl; return 0 ;}# include <Cstdio> # include <iostream> # include <cstring> # include <algorithm> using namespace std; # define N 22222 # define INF 0x7FFFFFFF/***** suffix array template *****/# define F (x)/3 + (x) % 3 = 1? 0: tb) // F (x) To find the starting position of suffix (x) of the original string in the new string # define G (x) <tb? (X) * 3 + 1 :( (x)-tb) * 3 + 2) // G (x) is the position of the new string suffix (x) in the original string, and F (x) are reciprocal operations int wa [N], wb [N], wv [N], WS [N]; int sa [N * 3]; // suffix smaller than I. The starting position is int rank1 [N] and height [N] in the source string. // rank the int r [N * 3] In the suffix arrangement with rank starting from I. // If the input is a string, used to calculate int c0 (int * r, int a, int B) {return r [a] = r [B] & r [a + 1] = r [B + 1] & r [a + 2] = r [B + 2];} int c12 (int k, int * r, int a, int B) {if (k = 2) return r [a] <r [B] | (r [a] = r [B] & c12 (1, r, a + 1, B + 1); else Return r [a] <r [B] | (r [a] = r [B] & wv [a + 1] <wv [B + 1]);} void sort (int * r, int * a, int * B, int n, int m) {int I; for (I = 0; I <n; I ++) wv [I] = r [a [I]; for (I = 0; I <m; I ++) WS [I] = 0; for (I = 0; I <n; I ++) WS [wv [I] ++; for (I = 1; I <m; I ++) WS [I] + = WS [I-1]; for (I = n-1; I> = 0; I --) B [-- WS [wv [I] = a [I]; return;} // Note: To facilitate recursive processing, the size of the r array and sa array is 3 * nvoid dc3 (int * r, int * sa, int n, int m) {// The rn array stores the new recursive string, and the san array is the sa int of the new string. I, j, * rn = r + n, * san = sa + n, ta = 0, tb = (n + 1)/3, tbc = 0, p; r [n] = r [n + 1] = 0; for (I = 0; I <n; I ++) {if (I % 3! = 0) wa [tbc ++] = I; // tbc indicates the number of suffixes where the modulo 3 is 1 or 2 at the starting position} sort (r + 2, wa, wb, tbc, m); sort (r + 1, wb, wa, tbc, m); sort (r, wa, wb, tbc, m); for (p = 1, rn [F (wb [0])] = 0, I = 1; I <tbc; I ++) rn [F (wb [I])] = c0 (r, wb [I-1], wb [I])? P-1: p ++; if (p <tbc) dc3 (rn, san, tbc, p); else {for (I = 0; I <tbc; I ++) san [rn [I] = I ;}// sorts all suffixes where the starting position modulo 3 is equal to 0 for (I = 0; I <tbc; I ++) {if (san [I] <tb) wb [ta ++] = san [I] * 3;} if (n % 3 = 1) // n % 3 = 1, special processing of suffix (n-1) wb [ta ++] = n-1; sort (r, wb, wa, ta, m ); for (I = 0; I <tbc; I ++) wv [wb [I] = G (san [I])] = I; // merge the sorting results of all suffixes and save them in the sa array for (I = 0, j = 0, p = 0; I <ta & j <tbc; p ++) sa [p] = c12 (wb [j] % 3, r, wa [I], wb [j])? Wa [I ++]: wb [j ++]; for (; I <ta; p ++) sa [p] = wa [I ++]; (; j <tbc; p ++) sa [p] = wb [j ++]; return ;}// height [I] = suffix (sa [I-1]) the longest public prefix of suffix (sa [I]), that is, the longest public prefix of the two adjacent suffixes void calheight (int * r, int * sa, int n) {int I, j, k = 0; for (I = 1; I <= n; I ++) rank1 [sa [I] = I; for (I = 0; I <n; height [rank1 [I ++] = k) for (k? K --: 0, j = sa [rank1 [I]-1]; r [I + k] = r [j + k]; k ++ );} bool judge (int mid, int n, int k) {int cnt = 1; for (int I = 1; I <= n; I ++) {if (height [I] >=mid) {cnt ++;} else cnt = 1; if (cnt> = k) return true;} return false ;} int xx [N], x [N]; int search (int v, int m) {int l = 0, r = m-1; while (l <= r) {int mid = (l + r)/2; if (x [mid] = v) return mid; if (v <x [mid]) r = mid-1; else l = mid + 1;} return-1;} int main (){ Int n, k; cin> n> k; for (int I = 0; I <n; I ++) {scanf ("% d ", & x [I]); xx [I] = x [I];} int m = 1; for (int I = 1; I <n; I ++) {// discretization deduplication if (x [I]! = X [I-1]) x [m ++] = x [I];} sort (x, x + m); for (int I = 0; I <n; I ++) r [I] = search (xx [I], m) + 1; // for (int I = 0; I <n; I ++) cout <r [I] <''; // cout <endl; r [n] = 0; // minimum end dc3 (r, sa, n +); calheight (r, sa, n); int l = 1, r = n, mid; // enumeration length int ans = 0; while (l <= r) {mid = (l + r)> 1; if (judge (mid, n, k) {ans = mid; l = mid + 1 ;}else {r = mid-1 ;}}cout <ans <endl; return 0 ;}