POJ 3261 Milk Patterns (suffix array + binary answer + discretization)

Source: Internet
Author: User

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 ;}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.