Resources:
Threads @ IIIT Hyderabad
Palindrome Substring Queries
Palindrome Substring Queries Implementation
CF blog
CF blog
E-maxx
uniqeSubstring Implementation
group identical implementation
Problems:
Substring Search
1517. Freedom of Choice
ADAPHOTO - Ada and Terramorphing
Minimal Shift
Cyclic Shifts
Sub-palindromes
Manacher's Algorithm
Strings - 3
Suffixes
Jitu and Strings
A2 online
H. Queries for Number of Palindromes
Implementation:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///https://acmp.ru/asp/do/index.asp?main=task&id_course=2&id_section=18&id_topic=42&id_problem=262&locale=en | |
/// Topic: hashing | |
/// O(n+m) | |
#include <bits/stdc++.h> | |
using namespace std; | |
#define INF 1<<30 | |
#define endl '\n' | |
#define maxn 100005 | |
#define tc printf("Case %d: ", cs) | |
#define tcn printf("Case %d:\n", cs); | |
#define FASTIO ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0); | |
typedef long long ll; | |
const double PI = acos(-1.0); | |
#define dbg1(x) cerr << #x << " = " << x << endl; | |
#define dbg2(x, y) cerr << #x << " = " << x << ", " << #y << " = " << y << endl; | |
#define dbg3(x, y, z) cerr << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
#define dbg4(w,x, y, z) cerr << #w << " = " << w << ", " <<#x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
template < typename F, typename S > | |
ostream& operator << ( ostream& os, const pair< F, S > & p ) { | |
return os << "(" << p.first << ", " << p.second << ")"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const vector< T > &v ) { | |
os << "{"; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << *it; | |
} | |
return os << "}"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const set< T > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin()) os << ", "; | |
os << *it; | |
} | |
return os << "]"; | |
} | |
template < typename F, typename S > | |
ostream &operator << ( ostream & os, const map< F, S > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << it -> first << " = " << it -> second ; | |
} | |
return os << "]"; | |
} | |
#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0) | |
clock_t tStart = clock(); | |
#define timeStamp dbg("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC) | |
void faltu () { cerr << endl; } | |
template <typename T> | |
void faltu( T a[], int n ) { | |
for (int i = 0; i < n; ++i) cerr << a[i] << ' '; | |
cerr << endl; | |
} | |
template <typename T, typename ... hello> | |
void faltu( T arg, const hello &... rest) { cerr << arg << ' '; faltu(rest...); } | |
// Program showing a policy-based data structure. | |
#include <ext/pb_ds/assoc_container.hpp> // Common file | |
#include <ext/pb_ds/tree_policy.hpp> | |
#include <functional> // for less | |
#include <iostream> | |
using namespace __gnu_pbds; | |
using namespace std; | |
// GNU link : https://goo.gl/WVDL6g | |
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, | |
tree_order_statistics_node_update> | |
new_data_set; | |
/**___________________________________________________**/ | |
typedef unsigned long long ull; | |
// Generate random base in (before, after) open interval: | |
int gen_base(const int before, const int after) { | |
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); | |
std::mt19937 mt_rand(seed); | |
int base = std::uniform_int_distribution<int>(before + 1, after)(mt_rand); | |
return base % 2 == 0 ? base - 1 : base; | |
} | |
struct Hash | |
{ | |
static const int mod = (int) 1e9 + 123; | |
static vector<int> pw1; // powers of base modulo mod | |
static vector<ull> pw2; // powers of base modulo 2^64 | |
static int base; | |
static inline int diff(int a, int b) | |
{ | |
return (a -= b) < 0 ? a + mod : a; | |
} | |
vector<int> pref1; // powers of base modulo mod | |
vector<ull> pref2; // powers of base modulo 2^64 | |
Hash(const string& s) | |
: pref1(s.size() + 1u, 0) | |
, pref2(s.size() + 1u, 0) | |
{ | |
assert(base < mod); | |
const int n = s.size(); // firstly calculated needed power of base | |
while ((int)pw1.size() <= n) { | |
pw1.push_back(1LL * pw1.back() * base % mod); | |
pw2.push_back(pw2.back() * base); | |
} | |
for (int i = 0; i < n; i++) { | |
assert(base > s[i]); | |
pref1[i + 1] = (pref1[i] + 1LL * s[i] * pw1[i]) % mod; | |
pref2[i + 1] = pref2[i] + s[i] * pw2[i]; | |
} | |
} | |
// Polynomial hash of subsequence [pos, pos+len) | |
// If mxPow != 0, value automatically multiply on base in needed power. Finally base ^ mxPow | |
inline pair<int, ull> operator()(const int pos, const int len, const int mxpow = 0)const { | |
int hash1 = pref1[pos + len] - pref1[pos]; | |
ull hash2 = pref2[pos + len] - pref2[pos]; | |
if (hash1 < 0) hash1 += mod; | |
if (mxpow != 0) { | |
hash1 = 1LL * hash1 * pw1[mxpow - (pos + len - 1)] % mod; | |
hash2 *= pw2[mxpow - (pos + len - 1)]; | |
} | |
return {hash1, hash2}; | |
} | |
}; | |
int Hash::base(1e9 + 7); | |
vector<int> Hash::pw1{1}; | |
vector<ull> Hash:: pw2{1}; | |
int main() | |
{ | |
// FASTIO | |
/* | |
#ifndef ONLINE_JUDGE | |
freopen("in.txt", "r", stdin); | |
freopen("out.txt", "w", stdout); | |
freopen("error.txt", "w", stderr); | |
#endif | |
//*/ | |
int T; | |
//scanf("%d", &T); | |
T = 1; | |
for (int cs = 1; cs <= T; cs++) { | |
char ch[100005]; | |
scanf("%s", ch); | |
string a(ch); | |
scanf("%s", ch); | |
string b(ch); | |
const int mxpow = max(a.size(), b.size()); | |
Hash::base = gen_base(256, Hash::mod); | |
Hash hash_a(a), hash_b(b); | |
//Copy needed hash from all string b: | |
const auto need = hash_b(0, (int)b.size(), mxpow); | |
//dbg(need); | |
for (int i = 0; i + (int)b.size() <= (int)a.size(); i++) { | |
if (hash_a(i, b.size(), mxpow) == need) { | |
printf("%d ", i); | |
} | |
} | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///http://acm.timus.ru/problem.aspx?space=1&num=1517 | |
// O(n log(n)^2) | |
#include <bits/stdc++.h> | |
using namespace std; | |
#define INF 1<<30 | |
#define endl '\n' | |
#define maxn 100005 | |
#define tc printf("Case %d: ", cs) | |
#define tcn printf("Case %d:\n", cs); | |
#define FASTIO ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0); | |
typedef long long ll; | |
const double PI = acos(-1.0); | |
#define dbg1(x) cerr << #x << " = " << x << endl; | |
#define dbg2(x, y) cerr << #x << " = " << x << ", " << #y << " = " << y << endl; | |
#define dbg3(x, y, z) cerr << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
#define dbg4(w,x, y, z) cerr << #w << " = " << w << ", " <<#x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
template < typename F, typename S > | |
ostream& operator << ( ostream& os, const pair< F, S > & p ) { | |
return os << "(" << p.first << ", " << p.second << ")"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const vector< T > &v ) { | |
os << "{"; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << *it; | |
} | |
return os << "}"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const set< T > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin()) os << ", "; | |
os << *it; | |
} | |
return os << "]"; | |
} | |
template < typename F, typename S > | |
ostream &operator << ( ostream & os, const map< F, S > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << it -> first << " = " << it -> second ; | |
} | |
return os << "]"; | |
} | |
#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0) | |
clock_t tStart = clock(); | |
#define timeStamp dbg("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC) | |
void faltu () { cerr << endl; } | |
template <typename T> | |
void faltu( T a[], int n ) { | |
for (int i = 0; i < n; ++i) cerr << a[i] << ' '; | |
cerr << endl; | |
} | |
template <typename T, typename ... hello> | |
void faltu( T arg, const hello &... rest) { cerr << arg << ' '; faltu(rest...); } | |
// Program showing a policy-based data structure. | |
#include <ext/pb_ds/assoc_container.hpp> // Common file | |
#include <ext/pb_ds/tree_policy.hpp> | |
#include <functional> // for less | |
#include <iostream> | |
using namespace __gnu_pbds; | |
using namespace std; | |
// GNU link : https://goo.gl/WVDL6g | |
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, | |
tree_order_statistics_node_update> | |
new_data_set; | |
/**___________________________________________________**/ | |
typedef unsigned long long ull; | |
// Generate random base in (before, after) open interval: | |
int gen_base(const int before, const int after) { | |
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); | |
std::mt19937 mt_rand(seed); | |
int base = std::uniform_int_distribution<int>(before + 1, after)(mt_rand); | |
return base % 2 == 0 ? base - 1 : base; | |
} | |
struct Hash | |
{ | |
static const int mod = (int) 1e9 + 123; | |
static vector<int> pw1; // powers of base modulo mod | |
static vector<ull> pw2; // powers of base modulo 2^64 | |
static int base; | |
static inline int diff(int a, int b) | |
{ | |
return (a -= b) < 0 ? a + mod : a; | |
} | |
vector<int> pref1; // powers of base modulo mod | |
vector<ull> pref2; // powers of base modulo 2^64 | |
Hash(const string& s) | |
: pref1(s.size() + 1u, 0) | |
, pref2(s.size() + 1u, 0) | |
{ | |
assert(base < mod); | |
const int n = s.size(); // firstly calculated needed power of base | |
while ((int)pw1.size() <= n) { | |
pw1.push_back(1LL * pw1.back() * base % mod); | |
pw2.push_back(pw2.back() * base); | |
} | |
for (int i = 0; i < n; i++) { | |
assert(base > s[i]); | |
pref1[i + 1] = (pref1[i] + 1LL * s[i] * pw1[i]) % mod; | |
pref2[i + 1] = pref2[i] + s[i] * pw2[i]; | |
} | |
} | |
// Polynomial hash of subsequence [pos, pos+len) | |
// If mxPow != 0, value automatically multiply on base in needed power. Finally base ^ mxPow | |
inline pair<int, ull> operator()(const int pos, const int len, const int mxpow = 0)const { | |
int hash1 = pref1[pos + len] - pref1[pos]; | |
ull hash2 = pref2[pos + len] - pref2[pos]; | |
if (hash1 < 0) hash1 += mod; | |
if (mxpow != 0) { | |
hash1 = 1LL * hash1 * pw1[mxpow - (pos + len - 1)] % mod; | |
hash2 *= pw2[mxpow - (pos + len - 1)]; | |
} | |
return {hash1, hash2}; | |
} | |
}; | |
int Hash::base(1e9 + 7); | |
vector<int> Hash::pw1{1}; | |
vector<ull> Hash:: pw2{1}; | |
int main() | |
{ | |
// FASTIO | |
///* | |
#ifndef ONLINE_JUDGE | |
freopen("in.txt", "r", stdin); | |
freopen("out.txt", "w", stdout); | |
freopen("error.txt", "w", stderr); | |
#endif | |
//*/ | |
int T; | |
//scanf("%d", &T); | |
T = 1; | |
for (int cs = 1; cs <= T; cs++) { | |
int n; | |
scanf("%d", &n); | |
char ch[100005]; | |
scanf("%s", ch); | |
string a(ch); | |
scanf("%s", ch); | |
string b(ch); | |
const int mxpow = max(a.size(), b.size()); | |
Hash::base = gen_base(256, Hash::mod); | |
Hash hash_a(a), hash_b(b); | |
int pos = -1, lw = 0, hi = min(a.size(), b.size()) + 1; | |
while (hi - lw > 1) { | |
int mid = (lw + hi) / 2; | |
vector<pair<int, ull>> hashes; | |
for (int i = 0; i + mid <= n; i++) { | |
hashes.push_back(hash_a(i, mid, mxpow)); | |
} | |
sort(hashes.begin(), hashes.end()); | |
int p = -1; | |
for (int i = 0; i + mid <= n; i++) { | |
if (binary_search(hashes.begin(), hashes.end(), hash_b(i, mid, mxpow))) { | |
p = i; | |
break; | |
} | |
} | |
if (p >= 0) { | |
lw = mid; | |
pos = p; | |
} | |
else { | |
hi = mid; | |
} | |
} | |
assert(pos >= 0); | |
printf("%s\n", b.substr(pos, lw).c_str()); | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///https://acmp.ru/asp/do/index.asp?main=task&id_course=2&id_section=18&id_topic=43&id_problem=284&locale=en | |
///nlog(n) | |
#include <bits/stdc++.h> | |
using namespace std; | |
#define INF 1<<30 | |
#define endl '\n' | |
#define maxn 100005 | |
#define tc printf("Case %d: ", cs) | |
#define tcn printf("Case %d:\n", cs); | |
#define FASTIO ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0); | |
typedef long long ll; | |
const double PI = acos(-1.0); | |
#define dbg1(x) cerr << #x << " = " << x << endl; | |
#define dbg2(x, y) cerr << #x << " = " << x << ", " << #y << " = " << y << endl; | |
#define dbg3(x, y, z) cerr << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
#define dbg4(w,x, y, z) cerr << #w << " = " << w << ", " <<#x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
template < typename F, typename S > | |
ostream& operator << ( ostream& os, const pair< F, S > & p ) { | |
return os << "(" << p.first << ", " << p.second << ")"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const vector< T > &v ) { | |
os << "{"; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << *it; | |
} | |
return os << "}"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const set< T > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin()) os << ", "; | |
os << *it; | |
} | |
return os << "]"; | |
} | |
template < typename F, typename S > | |
ostream &operator << ( ostream & os, const map< F, S > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << it -> first << " = " << it -> second ; | |
} | |
return os << "]"; | |
} | |
#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0) | |
clock_t tStart = clock(); | |
#define timeStamp dbg("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC) | |
void faltu () { cerr << endl; } | |
template <typename T> | |
void faltu( T a[], int n ) { | |
for (int i = 0; i < n; ++i) cerr << a[i] << ' '; | |
cerr << endl; | |
} | |
template <typename T, typename ... hello> | |
void faltu( T arg, const hello &... rest) { cerr << arg << ' '; faltu(rest...); } | |
// Program showing a policy-based data structure. | |
#include <ext/pb_ds/assoc_container.hpp> // Common file | |
#include <ext/pb_ds/tree_policy.hpp> | |
#include <functional> // for less | |
#include <iostream> | |
using namespace __gnu_pbds; | |
using namespace std; | |
// GNU link : https://goo.gl/WVDL6g | |
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, | |
tree_order_statistics_node_update> | |
new_data_set; | |
/**___________________________________________________**/ | |
typedef unsigned long long ull; | |
// Generate random base in (before, after) open interval: | |
int gen_base(const int before, const int after) { | |
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); | |
std::mt19937 mt_rand(seed); | |
int base = std::uniform_int_distribution<int>(before + 1, after)(mt_rand); | |
return base % 2 == 0 ? base - 1 : base; | |
} | |
struct Hash | |
{ | |
static const int mod = (int) 1e9 + 123; | |
static vector<int> pw1; // powers of base modulo mod | |
static vector<ull> pw2; // powers of base modulo 2^64 | |
static int base; | |
static inline int diff(int a, int b) | |
{ | |
return (a -= b) < 0 ? a + mod : a; | |
} | |
vector<int> pref1; // powers of base modulo mod | |
vector<ull> pref2; // powers of base modulo 2^64 | |
Hash(const string& s) | |
: pref1(s.size() + 1u, 0) | |
, pref2(s.size() + 1u, 0) | |
{ | |
assert(base < mod); | |
const int n = s.size(); // firstly calculated needed power of base | |
while ((int)pw1.size() <= n) { | |
pw1.push_back(1LL * pw1.back() * base % mod); | |
pw2.push_back(pw2.back() * base); | |
} | |
for (int i = 0; i < n; i++) { | |
assert(base > s[i]); | |
pref1[i + 1] = (pref1[i] + 1LL * s[i] * pw1[i]) % mod; | |
pref2[i + 1] = pref2[i] + s[i] * pw2[i]; | |
} | |
} | |
// Polynomial hash of subsequence [pos, pos+len) | |
// If mxPow != 0, value automatically multiply on base in needed power. Finally base ^ mxPow | |
inline pair<int, ull> operator()(const int pos, const int len, const int mxpow = 0)const { | |
int hash1 = pref1[pos + len] - pref1[pos]; | |
ull hash2 = pref2[pos + len] - pref2[pos]; | |
if (hash1 < 0) hash1 += mod; | |
if (mxpow != 0) { | |
hash1 = 1LL * hash1 * pw1[mxpow - (pos + len - 1)] % mod; | |
hash2 *= pw2[mxpow - (pos + len - 1)]; | |
} | |
return {hash1, hash2}; | |
} | |
}; | |
int Hash::base(1e9 + 7); | |
vector<int> Hash::pw1{1}; | |
vector<ull> Hash:: pw2{1}; | |
int main() | |
{ | |
// FASTIO | |
// /* | |
#ifndef ONLINE_JUDGE | |
freopen("in.txt", "r", stdin); | |
freopen("out.txt", "w", stdout); | |
freopen("error.txt", "w", stderr); | |
#endif | |
//*/ | |
int T; | |
//scanf("%d", &T); | |
T = 1; | |
for (int cs = 1; cs <= T; cs++) { | |
char ch[100005]; | |
scanf("%s", ch); | |
string a(ch); | |
int n = a.size(); | |
a += a; | |
const int mxpow = 2 * n; | |
Hash::base = gen_base(256, Hash::mod); | |
Hash hash(a); | |
vector<int> pos; | |
for (int i = 0; i < n; i++) { | |
pos.push_back(i); | |
} | |
auto p = *min_element(pos.begin(), pos.end(), [&](const int p1, const int p2) { | |
int lw = 0, hi = n + 1; | |
while (hi - lw > 1) { | |
int mid = (lw + hi) / 2; | |
if (hash(p1, mid, mxpow) == hash(p2, mid, mxpow)) | |
lw = mid; | |
else hi = mid; | |
} | |
return lw < n && a[p1 + lw] < a[p2 + lw]; | |
}); | |
printf("%s\n", a.substr(p, n).c_str()); | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///https://acmp.ru/asp/do/index.asp?main=task&id_course=2&id_section=18&id_topic=43&id_problem=286&locale=en | |
/// O(n log(n)^2) | |
#include <bits/stdc++.h> | |
using namespace std; | |
#define INF 1<<30 | |
#define endl '\n' | |
#define maxn 100005 | |
#define tc printf("Case %d: ", cs) | |
#define tcn printf("Case %d:\n", cs); | |
#define FASTIO ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0); | |
typedef long long ll; | |
const double PI = acos(-1.0); | |
#define dbg1(x) cerr << #x << " = " << x << endl; | |
#define dbg2(x, y) cerr << #x << " = " << x << ", " << #y << " = " << y << endl; | |
#define dbg3(x, y, z) cerr << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
#define dbg4(w,x, y, z) cerr << #w << " = " << w << ", " <<#x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
template < typename F, typename S > | |
ostream& operator << ( ostream& os, const pair< F, S > & p ) { | |
return os << "(" << p.first << ", " << p.second << ")"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const vector< T > &v ) { | |
os << "{"; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << *it; | |
} | |
return os << "}"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const set< T > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin()) os << ", "; | |
os << *it; | |
} | |
return os << "]"; | |
} | |
template < typename F, typename S > | |
ostream &operator << ( ostream & os, const map< F, S > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << it -> first << " = " << it -> second ; | |
} | |
return os << "]"; | |
} | |
#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0) | |
clock_t tStart = clock(); | |
#define timeStamp dbg("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC) | |
void faltu () { cerr << endl; } | |
template <typename T> | |
void faltu( T a[], int n ) { | |
for (int i = 0; i < n; ++i) cerr << a[i] << ' '; | |
cerr << endl; | |
} | |
template <typename T, typename ... hello> | |
void faltu( T arg, const hello &... rest) { cerr << arg << ' '; faltu(rest...); } | |
// Program showing a policy-based data structure. | |
#include <ext/pb_ds/assoc_container.hpp> // Common file | |
#include <ext/pb_ds/tree_policy.hpp> | |
#include <functional> // for less | |
#include <iostream> | |
using namespace __gnu_pbds; | |
using namespace std; | |
// GNU link : https://goo.gl/WVDL6g | |
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, | |
tree_order_statistics_node_update> | |
new_data_set; | |
/**___________________________________________________**/ | |
typedef unsigned long long ull; | |
// Generate random base in (before, after) open interval: | |
int gen_base(const int before, const int after) { | |
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); | |
std::mt19937 mt_rand(seed); | |
int base = std::uniform_int_distribution<int>(before + 1, after)(mt_rand); | |
return base % 2 == 0 ? base - 1 : base; | |
} | |
struct Hash | |
{ | |
static const int mod = (int) 1e9 + 123; | |
static vector<int> pw1; // powers of base modulo mod | |
static vector<ull> pw2; // powers of base modulo 2^64 | |
static int base; | |
static inline int diff(int a, int b) | |
{ | |
return (a -= b) < 0 ? a + mod : a; | |
} | |
vector<int> pref1; // powers of base modulo mod | |
vector<ull> pref2; // powers of base modulo 2^64 | |
Hash(const string& s) | |
: pref1(s.size() + 1u, 0) | |
, pref2(s.size() + 1u, 0) | |
{ | |
assert(base < mod); | |
const int n = s.size(); // firstly calculated needed power of base | |
while ((int)pw1.size() <= n) { | |
pw1.push_back(1LL * pw1.back() * base % mod); | |
pw2.push_back(pw2.back() * base); | |
} | |
for (int i = 0; i < n; i++) { | |
assert(base > s[i]); | |
pref1[i + 1] = (pref1[i] + 1LL * s[i] * pw1[i]) % mod; | |
pref2[i + 1] = pref2[i] + s[i] * pw2[i]; | |
} | |
} | |
// Polynomial hash of subsequence [pos, pos+len) | |
// If mxPow != 0, value automatically multiply on base in needed power. Finally base ^ mxPow | |
inline pair<int, ull> operator()(const int pos, const int len, const int mxpow = 0)const { | |
int hash1 = pref1[pos + len] - pref1[pos]; | |
ull hash2 = pref2[pos + len] - pref2[pos]; | |
if (hash1 < 0) hash1 += mod; | |
if (mxpow != 0) { | |
hash1 = 1LL * hash1 * pw1[mxpow - (pos + len - 1)] % mod; | |
hash2 *= pw2[mxpow - (pos + len - 1)]; | |
} | |
return {hash1, hash2}; | |
} | |
}; | |
int Hash::base(1e9 + 7); | |
vector<int> Hash::pw1{1}; | |
vector<ull> Hash:: pw2{1}; | |
int main() | |
{ | |
// FASTIO | |
/* | |
#ifndef ONLINE_JUDGE | |
freopen("in.txt", "r", stdin); | |
freopen("out.txt", "w", stdout); | |
freopen("error.txt", "w", stderr); | |
#endif | |
//*/ | |
int T; | |
//scanf("%d", &T); | |
T = 1; | |
for (int cs = 1; cs <= T; cs++) { | |
char ch[100005]; | |
scanf("%s", ch); | |
string a(ch); | |
int n = a.size(); | |
a += a; | |
const int mxpow = 2 * n; | |
Hash::base = gen_base(256, Hash::mod); | |
Hash hash(a); | |
vector<int> pos; | |
for (int i = 0; i < n; i++) { | |
pos.push_back(i); | |
} | |
stable_sort(pos.begin(), pos.end(), [&](const int p1, const int p2) { | |
int lw = 0, hi = n + 1; | |
while (hi - lw > 1) { | |
int mid = (lw + hi) / 2; | |
if (hash(p1, mid, mxpow) == hash(p2, mid, mxpow)) | |
lw = mid; | |
else hi = mid; | |
} | |
return lw < n && a[p1 + lw] < a[p2 + lw]; | |
}); | |
printf("%d\n", (int)(find(pos.begin(), pos.end(), 0) - pos.begin() ) + 1); | |
string ans; | |
for (auto x : pos) | |
{ | |
ans.push_back(a[x + n - 1]); | |
} | |
printf("%s\n", ans.c_str()); | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///https://acmp.ru/asp/do/index.asp?main=task&id_course=2&id_section=18&id_topic=43&id_problem=285&locale=en | |
///nlog(n) | |
#include <bits/stdc++.h> | |
using namespace std; | |
#define INF 1<<30 | |
#define endl '\n' | |
#define maxn 100005 | |
#define tc printf("Case %d: ", cs) | |
#define tcn printf("Case %d:\n", cs); | |
#define FASTIO ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0); | |
typedef long long ll; | |
const double PI = acos(-1.0); | |
#define dbg1(x) cerr << #x << " = " << x << endl; | |
#define dbg2(x, y) cerr << #x << " = " << x << ", " << #y << " = " << y << endl; | |
#define dbg3(x, y, z) cerr << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
#define dbg4(w,x, y, z) cerr << #w << " = " << w << ", " <<#x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
template < typename F, typename S > | |
ostream& operator << ( ostream& os, const pair< F, S > & p ) { | |
return os << "(" << p.first << ", " << p.second << ")"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const vector< T > &v ) { | |
os << "{"; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << *it; | |
} | |
return os << "}"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const set< T > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin()) os << ", "; | |
os << *it; | |
} | |
return os << "]"; | |
} | |
template < typename F, typename S > | |
ostream &operator << ( ostream & os, const map< F, S > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << it -> first << " = " << it -> second ; | |
} | |
return os << "]"; | |
} | |
#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0) | |
clock_t tStart = clock(); | |
#define timeStamp dbg("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC) | |
void faltu () { cerr << endl; } | |
template <typename T> | |
void faltu( T a[], int n ) { | |
for (int i = 0; i < n; ++i) cerr << a[i] << ' '; | |
cerr << endl; | |
} | |
template <typename T, typename ... hello> | |
void faltu( T arg, const hello &... rest) { cerr << arg << ' '; faltu(rest...); } | |
// Program showing a policy-based data structure. | |
#include <ext/pb_ds/assoc_container.hpp> // Common file | |
#include <ext/pb_ds/tree_policy.hpp> | |
#include <functional> // for less | |
#include <iostream> | |
using namespace __gnu_pbds; | |
using namespace std; | |
// GNU link : https://goo.gl/WVDL6g | |
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, | |
tree_order_statistics_node_update> | |
new_data_set; | |
/**___________________________________________________**/ | |
typedef unsigned long long ull; | |
// Generate random base in (before, after) open interval: | |
int gen_base(const int before, const int after) { | |
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); | |
std::mt19937 mt_rand(seed); | |
int base = std::uniform_int_distribution<int>(before + 1, after)(mt_rand); | |
return base % 2 == 0 ? base - 1 : base; | |
} | |
struct Hash | |
{ | |
static const int mod = (int) 1e9 + 123; | |
static vector<int> pw1; // powers of base modulo mod | |
static vector<ull> pw2; // powers of base modulo 2^64 | |
static int base; | |
static inline int diff(int a, int b) | |
{ | |
return (a -= b) < 0 ? a + mod : a; | |
} | |
vector<int> pref1; // powers of base modulo mod | |
vector<ull> pref2; // powers of base modulo 2^64 | |
Hash(const string& s) | |
: pref1(s.size() + 1u, 0) | |
, pref2(s.size() + 1u, 0) | |
{ | |
assert(base < mod); | |
const int n = s.size(); // firstly calculated needed power of base | |
while ((int)pw1.size() <= n) { | |
pw1.push_back(1LL * pw1.back() * base % mod); | |
pw2.push_back(pw2.back() * base); | |
} | |
for (int i = 0; i < n; i++) { | |
assert(base > s[i]); | |
pref1[i + 1] = (pref1[i] + 1LL * s[i] * pw1[i]) % mod; | |
pref2[i + 1] = pref2[i] + s[i] * pw2[i]; | |
} | |
} | |
// Polynomial hash of subsequence [pos, pos+len) | |
// If mxPow != 0, value automatically multiply on base in needed power. Finally base ^ mxPow | |
inline pair<int, ull> operator()(const int pos, const int len, const int mxpow = 0)const { | |
int hash1 = pref1[pos + len] - pref1[pos]; | |
ull hash2 = pref2[pos + len] - pref2[pos]; | |
if (hash1 < 0) hash1 += mod; | |
if (mxpow != 0) { | |
hash1 = 1LL * hash1 * pw1[mxpow - (pos + len - 1)] % mod; | |
hash2 *= pw2[mxpow - (pos + len - 1)]; | |
} | |
return {hash1, hash2}; | |
} | |
}; | |
int Hash::base(1e9 + 7); | |
vector<int> Hash::pw1{1}; | |
vector<ull> Hash:: pw2{1}; | |
int main() | |
{ | |
// FASTIO | |
/* | |
#ifndef ONLINE_JUDGE | |
freopen("in.txt", "r", stdin); | |
freopen("out.txt", "w", stdout); | |
freopen("error.txt", "w", stderr); | |
#endif | |
//*/ | |
int T; | |
//scanf("%d", &T); | |
T = 1; | |
for (int cs = 1; cs <= T; cs++) { | |
char ch[100005]; | |
scanf("%s", ch); | |
string a(ch); | |
int n = a.size(); | |
string b(a); | |
reverse(b.begin(), b.end()); | |
// const int mxpow = 2 * n; | |
Hash::base = gen_base(256, Hash::mod); | |
Hash hash_a(a) , hash_b(b); | |
vector<int> pos; | |
for (int i = 0; i < n; i++) { | |
pos.push_back(i); | |
} | |
ull ans = 0; | |
for (int i = 0, j = n - 1; i < n; ++i, --j) { | |
// odd length | |
int lw = 0, hi = min(n - i, n - j) + 1; | |
while (hi - lw > 1) { | |
int mid = (lw + hi) / 2; | |
if (hash_a(i, mid, n) == hash_b(j, mid, n)) | |
lw = mid; | |
else hi = mid; | |
} | |
ans += lw; | |
/// even length | |
lw = 0, hi = min(n - i - 1, n - j) + 1; | |
while (hi - lw > 1) { | |
int mid = (lw + hi) / 2; | |
if (hash_a(i + 1, mid, n) == hash_b(j, mid, n)) | |
lw = mid; | |
else hi = mid; | |
} | |
ans += lw; | |
} | |
cout << ans << endl; | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///https://acmp.ru/index.asp?main=task&id_task=829 | |
///Solution: polynomial hashes, sort, binary search, O(n log(n)) | |
#include <bits/stdc++.h> | |
using namespace std; | |
#define INF 1<<30 | |
#define endl '\n' | |
#define maxn 100005 | |
#define tc printf("Case %d: ", cs) | |
#define tcn printf("Case %d:\n", cs); | |
#define FASTIO ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0); | |
typedef long long ll; | |
const double PI = acos(-1.0); | |
#define dbg1(x) cerr << #x << " = " << x << endl; | |
#define dbg2(x, y) cerr << #x << " = " << x << ", " << #y << " = " << y << endl; | |
#define dbg3(x, y, z) cerr << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
#define dbg4(w,x, y, z) cerr << #w << " = " << w << ", " <<#x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
template < typename F, typename S > | |
ostream& operator << ( ostream& os, const pair< F, S > & p ) { | |
return os << "(" << p.first << ", " << p.second << ")"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const vector< T > &v ) { | |
os << "{"; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << *it; | |
} | |
return os << "}"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const set< T > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin()) os << ", "; | |
os << *it; | |
} | |
return os << "]"; | |
} | |
template < typename F, typename S > | |
ostream &operator << ( ostream & os, const map< F, S > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << it -> first << " = " << it -> second ; | |
} | |
return os << "]"; | |
} | |
#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0) | |
clock_t tStart = clock(); | |
#define timeStamp dbg("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC) | |
void faltu () { cerr << endl; } | |
template <typename T> | |
void faltu( T a[], int n ) { | |
for (int i = 0; i < n; ++i) cerr << a[i] << ' '; | |
cerr << endl; | |
} | |
template <typename T, typename ... hello> | |
void faltu( T arg, const hello &... rest) { cerr << arg << ' '; faltu(rest...); } | |
// Program showing a policy-based data structure. | |
#include <ext/pb_ds/assoc_container.hpp> // Common file | |
#include <ext/pb_ds/tree_policy.hpp> | |
#include <functional> // for less | |
#include <iostream> | |
using namespace __gnu_pbds; | |
using namespace std; | |
// GNU link : https://goo.gl/WVDL6g | |
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, | |
tree_order_statistics_node_update> | |
new_data_set; | |
/**___________________________________________________**/ | |
typedef unsigned long long ull; | |
// Generate random base in (before, after) open interval: | |
int gen_base(const int before, const int after) { | |
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); | |
std::mt19937 mt_rand(seed); | |
int base = std::uniform_int_distribution<int>(before + 1, after)(mt_rand); | |
return base % 2 == 0 ? base - 1 : base; | |
} | |
struct Hash | |
{ | |
static const int mod = (int) 1e9 + 123; | |
static vector<int> pw1; // powers of base modulo mod | |
static vector<ull> pw2; // powers of base modulo 2^64 | |
static int base; | |
static inline int diff(int a, int b) | |
{ | |
return (a -= b) < 0 ? a + mod : a; | |
} | |
vector<int> pref1; // powers of base modulo mod | |
vector<ull> pref2; // powers of base modulo 2^64 | |
Hash(const string& s) | |
: pref1(s.size() + 1u, 0) | |
, pref2(s.size() + 1u, 0) | |
{ | |
assert(base < mod); | |
const int n = s.size(); // firstly calculated needed power of base | |
while ((int)pw1.size() <= n) { | |
pw1.push_back(1LL * pw1.back() * base % mod); | |
pw2.push_back(pw2.back() * base); | |
} | |
for (int i = 0; i < n; i++) { | |
assert(base > s[i]); | |
pref1[i + 1] = (pref1[i] + 1LL * s[i] * pw1[i]) % mod; | |
pref2[i + 1] = pref2[i] + s[i] * pw2[i]; | |
} | |
} | |
// Polynomial hash of subsequence [pos, pos+len) | |
// If mxPow != 0, value automatically multiply on base in needed power. Finally base ^ mxPow | |
inline pair<int, ull> operator()(const int pos, const int len, const int mxpow = 0)const { | |
int hash1 = pref1[pos + len] - pref1[pos]; | |
ull hash2 = pref2[pos + len] - pref2[pos]; | |
if (hash1 < 0) hash1 += mod; | |
if (mxpow != 0) { | |
hash1 = 1LL * hash1 * pw1[mxpow - (pos + len - 1)] % mod; | |
hash2 *= pw2[mxpow - (pos + len - 1)]; | |
} | |
return {hash1, hash2}; | |
} | |
}; | |
int Hash::base(1e9 + 7); | |
vector<int> Hash::pw1{1}; | |
vector<ull> Hash:: pw2{1}; | |
int main() | |
{ | |
// FASTIO | |
// /* | |
#ifndef ONLINE_JUDGE | |
freopen("in.txt", "r", stdin); | |
freopen("out.txt", "w", stdout); | |
freopen("error.txt", "w", stderr); | |
#endif | |
//*/ | |
int T; | |
//scanf("%d", &T); | |
T = 1; | |
for (int cs = 1; cs <= T; cs++) { | |
char ch[100005]; | |
scanf("%s", ch); | |
string a(ch); | |
scanf("%s", ch); | |
string b(ch); | |
const int mxpow = max(a.size(), b.size() * 2); | |
Hash::base = gen_base(256, Hash::mod); | |
Hash hash_a(a) , hash_b(b+b); | |
vector<pair<int, ull>> hashes; | |
for (int i = 0; i < (int)b.size(); i++) { | |
hashes.push_back(hash_b(i, b.size(), mxpow)); | |
} | |
sort(hashes.begin(), hashes.end()); | |
int ans = 0; | |
for (int i = 0; i + (int)b.size() <= (int)a.size(); i++) { | |
ans += binary_search(hashes.begin(), hashes.end(), hash_a(i, b.size(), mxpow)); | |
} | |
cout << ans << endl; | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///https://www.hackerrank.com/contests/ab-yeh-kar-ke-dikhao/challenges/jitu-and-strings/problem | |
///Solution: polynomial hashes,binary search, O(n log(n)) | |
#include <bits/stdc++.h> | |
using namespace std; | |
#define INF 1<<30 | |
#define endl '\n' | |
#define maxn 100005 | |
#define tc printf("Case %d: ", cs) | |
#define tcn printf("Case %d:\n", cs); | |
#define FASTIO ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0); | |
typedef long long ll; | |
const double PI = acos(-1.0); | |
#define dbg1(x) cerr << #x << " = " << x << endl; | |
#define dbg2(x, y) cerr << #x << " = " << x << ", " << #y << " = " << y << endl; | |
#define dbg3(x, y, z) cerr << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
#define dbg4(w,x, y, z) cerr << #w << " = " << w << ", " <<#x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl; | |
template < typename F, typename S > | |
ostream& operator << ( ostream& os, const pair< F, S > & p ) { | |
return os << "(" << p.first << ", " << p.second << ")"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const vector< T > &v ) { | |
os << "{"; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << *it; | |
} | |
return os << "}"; | |
} | |
template < typename T > | |
ostream &operator << ( ostream & os, const set< T > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin()) os << ", "; | |
os << *it; | |
} | |
return os << "]"; | |
} | |
template < typename F, typename S > | |
ostream &operator << ( ostream & os, const map< F, S > &v ) { | |
os << "["; | |
for (auto it = v.begin(); it != v.end(); ++it) { | |
if ( it != v.begin() ) os << ", "; | |
os << it -> first << " = " << it -> second ; | |
} | |
return os << "]"; | |
} | |
#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0) | |
clock_t tStart = clock(); | |
#define timeStamp dbg("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC) | |
void faltu () { cerr << endl; } | |
template <typename T> | |
void faltu( T a[], int n ) { | |
for (int i = 0; i < n; ++i) cerr << a[i] << ' '; | |
cerr << endl; | |
} | |
template <typename T, typename ... hello> | |
void faltu( T arg, const hello &... rest) { cerr << arg << ' '; faltu(rest...); } | |
// Program showing a policy-based data structure. | |
#include <ext/pb_ds/assoc_container.hpp> // Common file | |
#include <ext/pb_ds/tree_policy.hpp> | |
#include <functional> // for less | |
#include <iostream> | |
using namespace __gnu_pbds; | |
using namespace std; | |
// GNU link : https://goo.gl/WVDL6g | |
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, | |
tree_order_statistics_node_update> | |
new_data_set; | |
/**___________________________________________________**/ | |
typedef unsigned long long ull; | |
// Generate random base in (before, after) open interval: | |
int gen_base(const int before, const int after) { | |
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); | |
std::mt19937 mt_rand(seed); | |
int base = std::uniform_int_distribution<int>(before + 1, after)(mt_rand); | |
return base % 2 == 0 ? base - 1 : base; | |
} | |
struct Hash | |
{ | |
static const int mod = 2147483647; | |
static vector<int> pw1; // powers of base modulo mod | |
static vector<ull> pw2; // powers of base modulo 2^64 | |
static int base; | |
static inline int diff(int a, int b) | |
{ | |
return (a -= b) < 0 ? a + mod : a; | |
} | |
static inline int MOD(ull x) | |
{ | |
x += mod; | |
x = (x >> 31) + (x & mod); | |
return int((x >> 31) + (x & mod)); | |
} | |
vector<int> pref1; // powers of base modulo mod | |
vector<ull> pref2; // powers of base modulo 2^64 | |
Hash(const string& s) | |
: pref1(s.size() + 1u, 0) | |
, pref2(s.size() + 1u, 0) | |
{ | |
assert(base < mod); | |
const int n = s.size(); // firstly calculated needed power of base | |
while ((int)pw1.size() <= n) { | |
pw1.push_back(MOD((ull)pw1.back()*base)); | |
pw2.push_back(pw2.back() * base); | |
} | |
for (int i = 0; i < n; i++) { | |
assert(base > s[i]); | |
pref1[i + 1] = MOD(pref1[i] + (ull)s[i] * pw1[i]); | |
pref2[i + 1] = pref2[i] + s[i] * pw2[i]; | |
} | |
} | |
// Polynomial hash of subsequence [pos, pos+len) | |
// If mxPow != 0, value automatically multiply on base in needed power. Finally base ^ mxPow | |
inline pair<int, ull> operator()(const int pos, const int len, const int mxpow = 0)const { | |
int hash1 = diff(pref1[pos + len] , pref1[pos]); | |
ull hash2 = pref2[pos + len] - pref2[pos]; | |
if (mxpow != 0) { | |
hash1 = MOD((ull) hash1 * pw1[mxpow - (pos + len - 1)]); | |
hash2 *= pw2[mxpow - (pos + len - 1)]; | |
} | |
return {hash1, hash2}; | |
} | |
inline pair<int, ull> prefix_after_swap(const int len, const int i, const int j, const char ci, const char cj) const { | |
// prefix before i: | |
int hash1 = pref1[min(len, i)]; | |
ull hash2 = pref2[min(len, i)]; | |
if (len <= i) return {hash1, hash2}; | |
// add symbol on position i after swap | |
hash1 = MOD(hash1 + (ull)cj * pw1[i]); | |
hash2 += cj * pw2[i]; | |
// Prefix prefore j: | |
hash1 = MOD(hash1 + (ull)diff(pref1[min(len, j)], pref1[i + 1])); | |
hash2 += pref2[min(len, j)] - pref2[i + 1]; | |
if (len <= j) return {hash1, hash2}; | |
// Add symbol on position j after swap: | |
hash1 = MOD(hash1 + (ull)ci * pw1[j]); | |
hash2 += ci * pw2[j]; | |
// Prefix before len: | |
hash1 = MOD(hash1 + (ull)diff(pref1[len], pref1[j + 1])); | |
hash2 += pref2[len] - pref2[j + 1]; | |
return {hash1, hash2}; | |
} | |
}; | |
int Hash::base(1e9 + 7); | |
vector<int> Hash::pw1{1}; | |
vector<ull> Hash:: pw2{1}; | |
int main() | |
{ | |
// FASTIO | |
// /* | |
#ifndef ONLINE_JUDGE | |
freopen("in.txt", "r", stdin); | |
freopen("out.txt", "w", stdout); | |
freopen("error.txt", "w", stderr); | |
#endif | |
//*/ | |
int T; | |
//scanf("%d", &T); | |
T = 1; | |
for (int cs = 1; cs <= T; cs++) { | |
int n; | |
scanf("%d", &n); | |
char ch[200005]; | |
scanf("%s", ch); | |
string a(ch); | |
scanf("%s", ch); | |
string b(ch); | |
//const int mxpow = max(a.size(), b.size() * 2); | |
Hash::base = gen_base(256, Hash::mod); | |
Hash hash_a(a) , hash_b(b); | |
int pos1 = 0; | |
while (pos1 < n && a[pos1] == b[pos1]) ++pos1; | |
int ans = pos1; | |
for (int pos2 = pos1 + 1; pos2 < n; pos2++) { | |
int lw = 0, hi = n + 1; | |
while (hi - lw > 1) { | |
const int mid = (lw + hi) / 2; | |
const auto hs = hash_a.prefix_after_swap(mid, pos1, pos2, a[pos1], a[pos2]); | |
if (hs == hash_b(0, mid)) | |
lw = mid; | |
else hi = mid; | |
} | |
ans = max(ans, lw); | |
} | |
cout << ans << endl; | |
} | |
return 0; | |
} |
No comments:
Post a Comment