let's start Code

Suffix Automaton

Resources:

cp-algorithms

saisumit

implementation

CF-blog

Good blogs


Implementation:

///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;
}
view raw CF-128B.cpp hosted with ❤ by GitHub
#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;
}
view raw CF_128B.cpp hosted with ❤ by GitHub
///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;
}
view raw SUBST1.cpp hosted with ❤ by GitHub


Share:

Related Posts:

No comments:

Post a Comment

About

let's start CODE

Popular Posts