Skip to content

Commit 5de6fc3

Browse files
committed
Initial commit
0 parents  commit 5de6fc3

31 files changed

+2883
-0
lines changed

aho_corasick.cpp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// aho_corasick.cpp
2+
// Eric K. Zhang; July 15, 2016
3+
4+
// Problem: Given a text string and a dictionary
5+
// of search strings, find all occurences of a search
6+
// string in the text (overlap included).
7+
8+
// Bad solution: Run KMP a lot, giving O(N * |S|)
9+
10+
// Good solution: Aho-Corasick gives O(N + sum|S|) by
11+
// essentially extending KMP, creating a trie with
12+
// "failure" functions. Basically a FSM.
13+
14+
// Note: The automation generated by Aho-Corasick can
15+
// also be used as a first step in many problems. This
16+
// is often how it'll be used (e.g. sparse table) in
17+
// competitions, since Rabin-Karp is easier to code
18+
// for the simple version of the problem.
19+
20+
#include <bits/stdc++.h>
21+
using namespace std;
22+
23+
typedef long long LL;
24+
25+
#define MAXN 100013
26+
int N; // size of dictionary
27+
string dict[MAXN];
28+
string text;
29+
30+
#define MAXM 100013
31+
int M; // number of states in the automation
32+
int g[MAXM][26]; // the normal edges in the trie
33+
int f[MAXM]; // failure function
34+
LL out[MAXM]; // output function
35+
36+
int aho_corasick() {
37+
memset(g, -1, sizeof g);
38+
memset(out, 0, sizeof out);
39+
40+
int nodes = 1;
41+
42+
// build the trie
43+
for (int i = 0; i < N; i++) {
44+
string& s = dict[i];
45+
int cur = 0;
46+
47+
for (int j = 0; j < s.size(); j++) {
48+
if (g[cur][s[j] - 'a'] == -1) {
49+
g[cur][s[j] - 'a'] = nodes++;
50+
}
51+
cur = g[cur][s[j] - 'a'];
52+
}
53+
out[cur]++;
54+
}
55+
56+
for (int ch = 0; ch < 26; ch++) {
57+
if (g[0][ch] == -1) {
58+
g[0][ch] = 0;
59+
}
60+
}
61+
62+
// BFS to calculate out and failure functions
63+
memset(f, -1, sizeof f);
64+
queue<int> q;
65+
for (int ch = 0; ch < 26; ch++) {
66+
if (g[0][ch] != 0) {
67+
f[g[0][ch]] = 0;
68+
q.push(g[0][ch]);
69+
}
70+
}
71+
72+
while (!q.empty()) {
73+
int state = q.front();
74+
q.pop();
75+
76+
for (int ch = 0; ch < 26; ch++) {
77+
if (g[state][ch] == -1) continue;
78+
79+
int fail = f[state];
80+
while (g[fail][ch] == -1) {
81+
fail = f[fail];
82+
}
83+
84+
f[g[state][ch]] = g[fail][ch];
85+
out[g[state][ch]] += out[g[fail][ch]];
86+
87+
q.push(g[state][ch]);
88+
}
89+
}
90+
91+
return nodes;
92+
}
93+
94+
LL search() {
95+
// Using the Aho-Corasick automation, search the text.
96+
int state = 0;
97+
LL ret = 0;
98+
for (char c : text) {
99+
while (g[state][c - 'a'] == -1) {
100+
state = f[state];
101+
}
102+
state = g[state][c - 'a'];
103+
ret += out[state];
104+
}
105+
// It's that simple!
106+
return ret;
107+
}
108+
109+
int main() {
110+
// make I/O faster
111+
ios_base::sync_with_stdio(false);
112+
cin.tie(0);
113+
114+
freopen("aho_corasick.in", "r", stdin);
115+
116+
cin >> N;
117+
for (int i = 0; i < N; i++) {
118+
cin >> dict[i];
119+
}
120+
cin >> text;
121+
122+
M = aho_corasick();
123+
LL result = search();
124+
125+
cout << result << endl;
126+
return 0;
127+
}

convex_hull_trick.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// convex_hull_trick.cpp
2+
// Eric K. Zhang; Nov. 22, 2017
3+
4+
#include <bits/stdc++.h>
5+
using namespace std;
6+
7+
typedef pair<int, int> pii;
8+
#define MAXN 100013
9+
int N, Q;
10+
pii ar[MAXN];
11+
12+
vector<pii> envelope;
13+
vector<double> hull;
14+
15+
double intersect(int m1, int b1, int m2, int b2) {
16+
return (b2 - b1) / ((double) m1 - m2);
17+
}
18+
19+
double intersect(pii y1, pii y2) {
20+
return intersect(y1.first, y1.second, y2.first, y2.second);
21+
}
22+
23+
int main() {
24+
// make cin, cout faster
25+
ios_base::sync_with_stdio(false);
26+
cin.tie(0);
27+
28+
freopen("cht.in", "r", stdin);
29+
30+
cin >> N >> Q;
31+
for (int i = 0; i < N; i++) {
32+
cin >> ar[i].first >> ar[i].second;
33+
}
34+
35+
// Ok, time for the CHT algorithm! We'll find the lower envelope
36+
sort(ar, ar + N, [](pii y1, pii y2) {
37+
return y1.first != y2.first ? y1.first > y2.first : y1.second < y2.second;
38+
});
39+
40+
for (int i = 0; i < N; i++) {
41+
if (i != 0 && ar[i].first == ar[i - 1].first)
42+
continue; // repeated slope <-> parallel lines
43+
44+
int sz;
45+
while ((sz = envelope.size()) >= 2) {
46+
if (intersect(envelope[sz - 2], ar[i]) <
47+
intersect(envelope[sz - 2], envelope[sz - 1])) {
48+
envelope.pop_back();
49+
}
50+
else break;
51+
}
52+
53+
envelope.push_back(ar[i]);
54+
}
55+
56+
for (int i = 0; i < envelope.size() - 1; i++) {
57+
hull.push_back(intersect(envelope[i], envelope[i + 1]));
58+
}
59+
60+
for (int i = 0; i < Q; i++) {
61+
double x;
62+
cin >> x;
63+
int idx = lower_bound(begin(hull), end(hull), x) - begin(hull);
64+
cout << envelope[idx].first * x + envelope[idx].second << '\n';
65+
}
66+
67+
cout.flush();
68+
return 0;
69+
}

euler_tour.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// euler_tour.cpp
2+
// Eric K. Zhang; Dec. 22, 2017
3+
4+
#include <bits/stdc++.h>
5+
using namespace std;
6+
7+
#define MAXN 100013
8+
#define MAXM 1000013
9+
int N, M;
10+
vector<pair<int, int> > adj[MAXN];
11+
int cur[MAXN];
12+
bool used[MAXM];
13+
vector<int> tour;
14+
15+
void dfs(int n) {
16+
while (cur[n] != adj[n].size()) {
17+
if (used[adj[n][cur[n]].second]) {
18+
++cur[n];
19+
continue;
20+
}
21+
auto p = adj[n][cur[n]++];
22+
used[p.second] = true;
23+
dfs(p.first);
24+
}
25+
tour.push_back(n);
26+
}
27+
28+
int main() {
29+
cin >> N >> M;
30+
for (int i = 0; i < M; i++) {
31+
int u, v;
32+
cin >> u >> v;
33+
--u; --v;
34+
adj[u].emplace_back(v, i);
35+
adj[v].emplace_back(u, i);
36+
}
37+
dfs(0);
38+
cout << tour.size() << endl;
39+
for (int v : tour) {
40+
cout << v + 1 << ' ';
41+
}
42+
cout << endl;
43+
return 0;
44+
}

fentreap.cpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// fentreap.cpp
2+
// Eric K. Zhang; Jan. 1, 2018
3+
4+
#include <bits/stdc++.h>
5+
using namespace std;
6+
7+
#define MAXN 100013
8+
#define MAXLGN 18
9+
10+
int N;
11+
12+
struct tnode {
13+
tnode* l;
14+
tnode* r;
15+
int x, y;
16+
int val, sum;
17+
tnode() { y = rand() ^ (rand() << 16); }
18+
void update() { sum = val + (l ? l->sum : 0) + (r ? r->sum : 0); }
19+
} vals[MAXN * MAXLGN];
20+
int mem = 0;
21+
tnode* fen[MAXN];
22+
23+
void split(tnode* t, tnode*& l, tnode*& r, int k) {
24+
if (!t) {
25+
l = r = nullptr;
26+
return;
27+
}
28+
if (t->x < k) {
29+
l = t;
30+
split(t->r, t->r, r, k);
31+
}
32+
else {
33+
r = t;
34+
split(t->l, l, t->l, k);
35+
}
36+
t->update();
37+
}
38+
39+
void merge(tnode*& t, tnode* l, tnode* r) {
40+
if (!l || !r) {
41+
t = l ? l : r;
42+
return;
43+
}
44+
if (l->y < r->y) {
45+
t = l;
46+
merge(t->r, t->r, r);
47+
}
48+
else {
49+
t = r;
50+
merge(t->l, l, t->l);
51+
}
52+
t->update();
53+
}
54+
55+
void upd(tnode*& t, int y, int val) {
56+
tnode *l, *r;
57+
split(t, l, t, y);
58+
split(t, t, r, y + 1);
59+
if (!t) t = &vals[mem++], t->x = y;
60+
t->val += val;
61+
t->update();
62+
merge(t, l, t);
63+
merge(t, t, r);
64+
}
65+
66+
void update(int x, int y, int val) {
67+
for (x++; x < MAXN; x += x & -x) {
68+
upd(fen[x], y, val);
69+
}
70+
}
71+
72+
int qry(tnode*& t, int y) {
73+
tnode* r;
74+
split(t, t, r, y + 1);
75+
int ret = t ? t->sum : 0;
76+
merge(t, t, r);
77+
return ret;
78+
}
79+
80+
int query(int x, int y) {
81+
int ret = 0;
82+
for (x++; x; x -= x & -x) {
83+
ret += qry(fen[x], y);
84+
}
85+
return ret;
86+
}
87+
88+
int main() {
89+
N = 100;
90+
update(0, 0, 5);
91+
update(2, 2, 30);
92+
update(3, 1, 10);
93+
update(0, 5, 10);
94+
cout << query(2, 4) << endl;
95+
}

fenwick_2d.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// fenwick_2d.cpp
2+
// Eric K. Zhang; Nov. 22, 2017
3+
4+
#include <bits/stdc++.h>
5+
using namespace std;
6+
7+
#define MAX 1000
8+
9+
int N, M;
10+
int fenwick[MAX + 1][MAX + 1];
11+
12+
void update(int x, int y, int val) {
13+
for (int a = x; a <= MAX; a += a & -a) {
14+
for (int b = y; b <= MAX; b += b & -b) {
15+
fenwick[a][b] += val;
16+
}
17+
}
18+
}
19+
20+
int query(int x, int y) {
21+
int ans = 0;
22+
for (int a = x; a > 0; a -= a & -a) {
23+
for (int b = y; b > 0; b -= b & -b) {
24+
ans += fenwick[a][b];
25+
}
26+
}
27+
return ans;
28+
}
29+
30+
int main() {
31+
cin >> N >> M;
32+
for (int i = 0; i < N; i++) {
33+
int A, B;
34+
cin >> A >> B;
35+
update(A, B, 1);
36+
}
37+
for (int i = 0; i < M; i++) {
38+
int A, B;
39+
cin >> A >> B;
40+
cout << query(A, B) << '\n';
41+
}
42+
cout.flush();
43+
return 0;
44+
}

0 commit comments

Comments
 (0)