diff --git a/content/kactl.tex b/content/kactl.tex index 25beecd..631baa7 100644 --- a/content/kactl.tex +++ b/content/kactl.tex @@ -21,6 +21,7 @@ \kactlchapter{contest} \kactlchapter{data-structures} \kactlchapter{graph} + \kactlchapter{string} \kactlchapter{number-theory} \kactlchapter{geometry} \kactlchapter{math} diff --git a/content/string/chapter.tex b/content/string/chapter.tex new file mode 100644 index 0000000..07425a3 --- /dev/null +++ b/content/string/chapter.tex @@ -0,0 +1,3 @@ +\chapter{String} + +\kactlimport{manacher.cpp} diff --git a/content/string/manacher.cpp b/content/string/manacher.cpp new file mode 100644 index 0000000..d7a2a43 --- /dev/null +++ b/content/string/manacher.cpp @@ -0,0 +1,52 @@ +/** + * Author: me + * Description: Find longest palindrome centered at each index. + * Initialise with original 0-indexed string. QUERYING IS 1-INDEXED. + * Time: $O(N)$ + */ + +struct Manacher { + string s; + vector pl; + + void calc() { + int n = s.length() - 1; + int l = 0, r = 0; + + for (int i = 1; i <= n; i += 1) { + if (i < r) pl[i] = min(r-i, pl[l+r-i]); + while (s[i-pl[i]-1] == s[i+pl[i]+1]) pl[i] += 1; + if (i + pl[i] > r) { + l = i - pl[i]; + r = i + pl[i]; + } + } + } + + Manacher() {} + void init(string _s, char f='~') { + s = "@"; s += f; + for (char c: _s) + {s += c; s += f;} s += '|'; + pl.resize(s.length(), 0); + calc(); + } + + // Query for substring [l, r] + // on original string with 1-indexed + bool is_palindrome(int l, int r) { + l <<= 1; r <<= 1; + int mid = (l+r) >> 1; + return mid + pl[mid] >= r; + } +}; +/* +Manacher mana; + +void example() { + string s; + cin >> s; + mana.init(s); + int l, r; cin >> l >> r; + cout << mana.is_palindrome(l, r); +}*/ diff --git a/kactl.pdf b/kactl.pdf index 006c6de..73f5cec 100644 Binary files a/kactl.pdf and b/kactl.pdf differ diff --git a/lab/code b/lab/code new file mode 100755 index 0000000..a787707 Binary files /dev/null and b/lab/code differ diff --git a/lab/code.cpp b/lab/code.cpp new file mode 100644 index 0000000..705bf7e --- /dev/null +++ b/lab/code.cpp @@ -0,0 +1,59 @@ +/** + * Author: me + * Description: Find longest palindrome centered at each index. + * Initialise with original 0-indexed string. QUERYING IS 1-INDEXED. + * Time: $O(N)$ + */ + +#include +using namespace std; + +struct Manacher { + string s; + vector pl; + + void calc() { + int n = s.length() - 1; + int l = 0, r = 0; + + for (int i = 1; i <= n; i += 1) { + if (i < r) pl[i] = min(r-i, pl[l+r-i]); + while (s[i-pl[i]-1] == s[i+pl[i]+1]) pl[i] += 1; + if (i + pl[i] > r) { + l = i - pl[i]; + r = i + pl[i]; + } + } + } + + Manacher() {} + void init(string _s, char f='~') { + s = "@"; s += f; + for (char c: _s) + {s += c; s += f;} s += '|'; + pl.resize(s.length(), 0); + calc(); + } + + // Query for substring [l, r] + // on original string with 1-indexed + bool is_palindrome(int l, int r) { + l <<= 1; r <<= 1; + int mid = (l+r) >> 1; + return mid + pl[mid] >= r; + } +}; + +Manacher mana; + +void example() { + string s; + cin >> s; + mana.init(s); + int l, r; cin >> l >> r; + cout << mana.is_palindrome(l, r); +} + +int main() { + example(); +} diff --git a/lab/sparse_table.cpp b/lab/sparse_table.cpp deleted file mode 100644 index e5411cb..0000000 --- a/lab/sparse_table.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Author: me - * Description: Sparse table for static RMQ. - * This version is 1-indexed - * Time: $O(N \log N + Q)$ - */ - -struct SparseTable { - int n; - // st[i][j] = min/max in segment len 2^i start at j - vector> st; - - SparseTable() {} - void init(int _n, int* a) { - n = _n; - int lg2 = __lg(n) + 2; - st.resize(lg2, vector(n+1)); - for (int i = 1; i <= n; i += 1) st[0][i] = a[i]; - - for (int i = 1; i < lg2; i += 1) - for (int j = 1; j <= n; j += 1) - // CAREFUL MIN-MAX - st[i][j] = min(st[i-1][j], st[i-1][j + (1 << (i-1))]); - } - - // Query for [l, r] - int retrieve(int l, int r) { - int i = __lg(r-l+1); - //CAREFUL MIN-MAX - return min(st[i][l], st[i][r - (1 << i) + 1]); - } -}; - -/* -SparseTable rmq; - -void example(int n, int q) { - int a[n+1]; - for (int i = 1; i <= n; i += 1) cin >> a[i]; - rmq.init(n, a); - while (q--) { - int l, r; - cin >> l >> r; - cout << rmq.retrieve(l, r) << "\n"; - } -} -*/