Resources:
cp-algorithms
saisumit
implementation
CF-blog
Good blogs
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://codeforces.com/problemset/problem/128/B | |
#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; | |
/**___________________________________________________**/ | |
const int N = 160000; | |
struct suffix_automata | |
{ | |
struct state | |
{ | |
int len = 0, link = -1; | |
map<char, int> to; | |
ll cnt1 = 0, cnt2 = 0; | |
} st[N]; | |
int last = 0, sz = 1; | |
void add_letter(char c) | |
{ | |
int cur = sz++; | |
int p = last; | |
last = cur; | |
st[cur].len = st[p].len + 1; | |
for (; p != -1 && !st[p].to[c]; p = st[p].link) | |
st[p].to[c] = cur; | |
if (p == -1) { | |
st[cur].link = 0; | |
return; | |
} | |
int q = st[p].to[c]; | |
if (st[q].len == st[p].len + 1) { | |
st[cur].link = q; | |
return; | |
} | |
int cl = sz++; | |
st[cl] = st[q]; | |
st[cl].len = st[p].len + 1; | |
st[cur].link = st[q].link = cl; | |
for (; p != -1 && st[p].to[c] == q; p = st[p].link) | |
st[p].to[c] = cl; | |
} | |
void build(string &s) | |
{ | |
for (int i = 0; i < (int)s.size(); i++) add_letter(s[i]); | |
used.assign(sz, 0); | |
dfs(0); | |
} | |
vector<int> used; | |
void dfs(int x) | |
{ | |
used[x] = 1; | |
for (auto it : st[x].to) { | |
if (!used[it.second]) dfs(it.second); | |
if (it.first == '#') st[x].cnt1++; | |
else st[x].cnt1 += st[it.second].cnt1; | |
st[x].cnt2 += st[it.second].cnt2; | |
} | |
st[x].cnt2 += st[x].cnt1; | |
} | |
void order(int cur, int k, string &ans, int x) | |
{ | |
if (cur >= k) return; | |
for (auto it = st[x].to.begin(); it != st[x].to.end(); it++) { | |
if (cur + st[it->second].cnt2 >= k) { | |
cur += st[it->second].cnt1; | |
ans += it->first; | |
order(cur, k, ans, it->second); | |
return; | |
} | |
else { | |
cur += st[it->second].cnt2; | |
} | |
} | |
ans = "No such line."; | |
} | |
string order(int k) | |
{ | |
string ret; | |
order(0, k, ret, 0); | |
return ret; | |
} | |
} ank; | |
int main() | |
{ | |
FASTIO | |
///* | |
#ifndef ONLINE_JUDGE | |
freopen("in.txt", "r", stdin); | |
freopen("out.txt", "w", stdout); | |
freopen("error.txt", "w", stderr); | |
#endif | |
//*/ | |
string s; | |
cin >> s; | |
s += '#'; | |
int k; | |
cin >> k; | |
ank.build(s); | |
cout << ank.order(k) << 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
#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; | |
/**___________________________________________________**/ | |
struct suffixAutomaton { | |
vector<map<char, int> > edges; | |
vector<int> link; | |
vector<int> length; | |
int last; | |
vector<bool> terminals; | |
suffixAutomaton(string s) { | |
edges.push_back(map<char, int> ()); | |
link.push_back(-1); | |
length.push_back(0); | |
last = 0; | |
for (int i = 0; i < (int)s.size(); i++) { | |
edges.push_back(map<char, int> ()); | |
length.push_back(i + 1); | |
link.push_back(0); | |
int r = edges.size() - 1; | |
//add edges to r and find p with link to q | |
int p = last; | |
while (p >= 0 && edges[p].find(s[i]) == edges[p].end()) { | |
edges[p][s[i]] = r; | |
p = link[p]; | |
} | |
if (p != -1) { | |
int q = edges[p][s[i]]; | |
if (length[p] + 1 == length[q]) { | |
//we don not have to split q, just set the correct suffix link | |
link[r] = q; | |
} | |
else { | |
// we have to split , add q | |
edges.push_back(edges[q]); | |
length.push_back(length[p] + 1); | |
link.push_back(link[q]); | |
int qq = edges.size() - 1; | |
link[q] = qq; | |
link[r] = qq; | |
// move short classes to q to point q | |
while (p >= 0 && edges[p][s[i]] == q) { | |
edges[p][s[i]] = qq; | |
p = link[p]; | |
} | |
} | |
} | |
last = r; | |
} | |
terminals = vector<bool> ((int)edges.size()); | |
int p = last; | |
while (p > 0) { | |
terminals[p] = 1; | |
p = link[p]; | |
} | |
} | |
}; | |
void dfs(suffixAutomaton &a, vector<ll> &occurences, vector<ll> &words, int i) | |
{ | |
ll occ = 0, wrd = 0; | |
if (occurences[i] != 0) return; | |
if (a.terminals[i]) { | |
occ++; | |
wrd++; | |
} | |
for (auto it : a.edges[i]) { | |
dfs(a, occurences, words, it.second); | |
occ += occurences[it.second]; | |
wrd += words[it.second] + occurences[it.second]; | |
} | |
occurences[i] = occ; | |
words[i] = wrd; | |
} | |
int main() | |
{ | |
FASTIO | |
///* | |
#ifndef ONLINE_JUDGE | |
freopen("in.txt", "r", stdin); | |
freopen("out.txt", "w", stdout); | |
freopen("error.txt", "w", stderr); | |
#endif | |
//*/ | |
string s; | |
cin >> s; | |
ll n = s.size(); | |
ll k; | |
cin >> k; | |
if (n * (n - 1) / 2 + n < k) { | |
cout << "No such line.\n"; | |
return 0; | |
} | |
suffixAutomaton a(s); | |
vector<ll> words(a.edges.size()); | |
vector<ll> occurences(a.edges.size()); | |
dfs(a, occurences, words, 0); | |
ll node = 0; | |
string t; | |
while (k > 0) { | |
ll acc = 0; | |
for (auto it : a.edges[node]) { | |
ll tmp = acc; | |
acc += words[it.second]; | |
if (acc >= k) { | |
node = it.second; | |
k -= tmp + occurences[it.second]; | |
t += it.first; | |
break; | |
} | |
} | |
} | |
cout << t << endl; | |
} |
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.spoj.com/problems/SUBST1/ | |
#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; | |
/**___________________________________________________**/ | |
class SAutomata | |
{ | |
class SNode { | |
public: | |
int link, len; | |
map<char, int> next; | |
SNode() { | |
link = -1; | |
len = 0; | |
} | |
SNode(const SNode& other) { | |
link = other.link; | |
len = other.len; | |
next = other.next; | |
} | |
}; | |
vector<SNode> nodes; | |
vector<ll> dp; | |
int last, cur; | |
void dfs(int node) | |
{ | |
if (dp[node] != -1) return; | |
for (auto it : nodes[node].next) | |
dfs(it.second); | |
ll sm = 0; | |
for (auto it : nodes[node].next) | |
sm += dp[it.second]; | |
dp[node] = 1 + sm; | |
} | |
ll dfs2(int node) | |
{ | |
if (dp[node] != -1) return 0; | |
dp[node] = 0; | |
ll ans = 0; | |
for (auto it : nodes[node].next) | |
ans += dfs2(it.second); | |
if (node != 0) ans += (nodes[node].len - nodes[nodes[node].link].len); | |
return ans; | |
} | |
public: | |
SAutomata(string S) | |
: nodes(2 * S.size()), | |
dp(2 * S.size(), -1), | |
last(0), | |
cur(1) | |
{ | |
for (int i = 0; i < (int)S.size(); i++) | |
add_char(S[i]); | |
} | |
void add_char(char A) | |
{ | |
//trace(A); | |
int nw = cur++; | |
nodes[nw].len = nodes[last].len + 1; | |
int p = last; | |
for (; p != -1 && nodes[p].next.find(A) == nodes[p].next.end(); p = nodes[p].link) | |
nodes[p].next[A] = nw; | |
if (p == -1) { | |
nodes[nw].link = 0; | |
} | |
else if (nodes[nodes[p].next[A]].len == nodes[p].len + 1) { | |
nodes[nw].link = nodes[p].next[A]; | |
} | |
else { | |
int nxt = nodes[p].next[A]; | |
int clone = cur++; | |
nodes[clone] = nodes[nxt]; | |
nodes[clone].len = nodes[p].len + 1; | |
nodes[nxt].link = clone; | |
nodes[nw].link = clone; | |
for (; p != -1 && nodes[p].next.find(A) != nodes[p].next.end() && nodes[p].next[A] == nxt; p = nodes[p].link) | |
nodes[p].next[A] = clone; | |
} | |
last = nw; | |
} | |
ll count_distinct() | |
{ | |
return dfs2(0); | |
dfs(0); | |
//for (int i = 0; i <= last; i++) | |
//trace(i, dp[i]); | |
return dp[0] - 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; | |
cin >> T; | |
for (int cs = 1; cs <= T; cs++) { | |
string s; | |
cin >> s; | |
auto mata = SAutomata(s); | |
cout << mata.count_distinct() << endl; | |
} | |
return 0; | |
} |
No comments:
Post a Comment