-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathsi17c1p4.cpp
137 lines (137 loc) · 4.28 KB
/
si17c1p4.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Ivan Carvalho
// Solution to https://dmoj.ca/problem/si17c1p4
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD1 = 1e9 + 9;
const ll prime1 = 999983;
const ll MOD2 = 1e9 + 7;
const ll prime2 = 999979;
const ll invprime1 = 943912055;
const ll invprime2 = 672490127;
const int MAXN = 2 * 1e5 + 10;
ll hash1[MAXN], pot1[MAXN], invpot1[MAXN];
int N, M, logaritmo[MAXN], comprimento[MAXN], dp[4 * MAXN];
string s1, s2, entrada;
vector<int> SArray, ida, volta;
inline ll get_hash1(int a, int b) {
ll val = ((hash1[b] - hash1[a - 1]) * invpot1[a - 1]) % MOD1;
if (val < 0) val += MOD1;
return val;
}
int LCP(int idx1, int idx2, int tam) {
for (int i = 0; i <= min(tam, 15); i++) {
if (entrada[idx1 - 1 + i] != entrada[idx2 - 1 + i]) return i;
if (tam == i + 1) return tam;
}
int atual = 0;
for (int i = logaritmo[tam]; i >= 0; i--) {
int novo = atual + (1 << i);
if (novo <= tam && get_hash1(idx1, idx1 + novo - 1) ==
get_hash1(idx2, idx2 + novo - 1)) {
atual = novo;
}
}
return atual;
}
int compara(int idx1, int idx2) {
int tam = (N + M + 1) - max(idx1, idx2) + 1;
int prefixo = LCP(idx1, idx2, tam);
if (prefixo == tam) {
return idx1 > idx2;
}
return entrada[idx1 - 1 + prefixo] < entrada[idx2 - 1 + prefixo];
}
template <class Iter>
void merge_sort(Iter first, Iter last) {
if (last - first > 1) {
Iter middle = first + (last - first) / 2;
merge_sort(first, middle); // [first, middle)
merge_sort(middle, last); // [middle, last)
std::inplace_merge(first, middle, last, compara);
}
}
void update(int pos, int left, int right, int x, int y) {
if (left == right) {
dp[pos] = y;
return;
}
int mid = (left + right) / 2;
if (x <= mid)
update(2 * pos, left, mid, x, y);
else
update(2 * pos + 1, mid + 1, right, x, y);
dp[pos] = min(dp[2 * pos], dp[2 * pos + 1]);
}
int query(int pos, int left, int right, int i, int j) {
if (left >= i && right <= j) return dp[pos];
int mid = (left + right) / 2;
if (j <= mid)
return query(2 * pos, left, mid, i, j);
else if (i >= mid + 1)
return query(2 * pos + 1, mid + 1, right, i, j);
return min(query(2 * pos, left, mid, i, j),
query(2 * pos + 1, mid + 1, right, i, j));
}
int main() {
cin >> s1;
N = s1.size();
s1.push_back('.');
cin >> s2;
M = s2.size();
entrada = s1 + s2;
pot1[0] = invpot1[0] = 1;
for (int i = 1; i <= N + M + 1; i++) {
pot1[i] = (pot1[i - 1] * prime1) % MOD1;
invpot1[i] = (invpot1[i - 1] * invprime1) % MOD1;
logaritmo[i] = logaritmo[i / 2] + 1;
hash1[i] = (hash1[i - 1] + pot1[i] * entrada[i - 1]) % MOD1;
SArray.push_back(i);
ida.push_back(0);
volta.push_back(0);
}
merge_sort(SArray.begin(), SArray.end());
for (int pos = 0; pos < SArray.size(); pos++) {
if (pos != 0)
ida[pos] = ida[pos - 1];
else
ida[pos] = -1;
if (SArray[pos] <= N) ida[pos] = SArray[pos];
}
for (int pos = SArray.size() - 1; pos >= 0; pos--) {
if (pos + 1 < SArray.size())
volta[pos] = volta[pos + 1];
else
volta[pos] = -1;
if (SArray[pos] <= N) volta[pos] = SArray[pos];
}
for (int pos = 0; pos < SArray.size(); pos++) {
int idx = SArray[pos];
if (idx <= N + 1) continue;
int i = ida[pos];
int j = volta[pos];
// printf("I %c %d %d %d\n",entrada[idx-1],idx,i,j);
int tam = 0;
if (i != -1) tam = LCP(i, idx, (N + M + 1) - max(i, idx) + 1);
if (j != -1) tam = max(tam, LCP(j, idx, (N + M + 1) - max(j, idx) + 1));
comprimento[idx - (N + 1)] = tam;
}
for (int i = 1; i <= M; i++) {
if (comprimento[i] == 0) {
printf("-1\n");
return 0;
}
}
for (int i = 1; i <= 4 * (M + 1); i++) dp[i] = MAXN;
update(1, 1, M + 1, M + 1, 0);
for (int i = M; i >= 1; i--) {
update(1, 1, M + 1, i,
query(1, 1, M + 1, i + 1, i + comprimento[i]) + 1);
}
printf("%d\n", query(1, 1, M + 1, 1, 1));
return 0;
}
}
printf("%d\n", query(1, 1, M + 1, 1, 1));
return 0;
}