-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathptoss.cpp
156 lines (138 loc) · 3.42 KB
/
ptoss.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <iostream>
#include <vector>
using namespace std;
const long long mod = 1000000007;
int pi[1000100];
template <typename T>
void print_vec(vector<T> v) {
for (int i=0; i<v.size(); i++) {
cout << v[i] << " ";
}
cout << endl;
}
template <typename T>
void print_arr(T a[], size_t size) {
for (int i=0; i<size; i++) {
cout << a[i] << " ";
}
cout << endl;
}
int value(char c) {
if (c >= 'a' && c <= 'z') {
return c - 'a';
} else if (c >= 'A' && c <= 'F') {
return c - 'A' + 26;
} else {
cout << "Unexpected character " << c << endl;
exit(1);
}
}
vector<bool> int_to_binary(int n) {
// Transform int to binary string
string s;
while (n!=0) {
s = (n%2==0 ? "0" : "1") + s;
n/=2;
}
// Fill string with 0
while (s.length() < 5) {
s.insert(0, "0");
}
// Transform string to list of boolean
vector<bool> binary;
for (int i=0; i<5; i++) {
binary.push_back(s[i]=='1' ? true : false);
}
return binary;
}
string str_to_fb(string s) {
// Initialize a list of boolean
vector<bool> binary_list;
binary_list.reserve(5 * s.length());
for (int i=0; i < s.length(); i++) {
int v = value(s[i]);
// Transform v in binary
vector<bool> binary = int_to_binary(v);
binary_list.insert(binary_list.end(), binary.begin(), binary.end());
}
// Transform binary_list in string with FB
string fb(5 * s.length(), ' ');
for (int i=0; i < 5*s.length(); i++) {
fb[i] = binary_list[i]==true ? 'B' : 'F';
}
// cout << s << " -> " << fb << "\n";
return fb;
}
void compute_prefix_kmp(string a) {
pi[0] = 0;
for (int i=1; i<a.length(); i++) {
int j = pi[i-1];
while (j>0 && a[i]!=a[j]) {
j = pi[j-1];
}
if (a[i] == a[j]) {
j++;
}
pi[i] = j;
}
}
int main() {
int tests;
cin >> tests;
while (tests--) {
// Read the two lines in input
int n, m;
string s1, s2;
cin >> n >> s1 >> m >> s2;
// Transform s1 and s2
string lucky_seq = str_to_fb(s1);
string toss_history = str_to_fb(s2);
// Compute the prefix on the lucky sequence
compute_prefix_kmp(lucky_seq);
// cout << "pi: ";
// print_arr(pi, n);
// Solve the problem
// string output = "lucky sequence: " + lucky_seq.substr(0,n) + "\nhistory: " + toss_history.substr(0,m);
// cout << output << endl;
// Build the arrays to use to find the solution
int tmp1[1000100]; // number of tosses for each letter in the lucky sequence
int tmp2[1000100]; // support array
tmp1[0] = 0;
tmp1[1] = -2;
tmp2[0] = 0;
for (int i=1; i<n; i++) {
if (lucky_seq[pi[i-1]] == lucky_seq[i]) {
tmp1[i + 1] = 2*tmp1[i] - tmp1[tmp2[pi[i - 1]]] - 2;
tmp2[i] = tmp2[pi[i - 1]];
} else {
tmp1[i + 1] = 2*tmp1[i] - tmp1[pi[i - 1] + 1] - 2;
tmp2[i] = pi[i - 1] + 1;
}
// tmp1[i+1] %= mod;
while (tmp1[i+1] > mod) tmp1[i+1] -= mod;
while (tmp1[i+1] < 0) tmp1[i+1] += mod;
}
// cout << "tmp1: ";
// print_arr(tmp1, n+1);
// cout << "tmp2: ";
// print_arr(tmp2, n+1);
// Find curr as the index of the state of the history the chef is
int curr = 0;
for (int i=0; i<m && curr!=n; i++) {
// cout << "curr=" << curr << endl;
while (curr > 0 && toss_history[i] != lucky_seq[curr]) {
// cout << "while i=" << i << endl;
curr = pi[curr - 1];
}
if (toss_history[i] == lucky_seq[curr]) {
// cout << "uguali i=" << i << endl;
curr++;
}
}
// cout << "curr: " << curr << endl;
// Print solution
long sol = (mod - (tmp1[n] - tmp1[curr] + mod) % mod) % mod;
cout << sol << "\n";
}
return 0;
}