-
Notifications
You must be signed in to change notification settings - Fork 62
/
Copy pathmutable_string_bitset.cpp
52 lines (40 loc) · 1.57 KB
/
mutable_string_bitset.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
#include <vector>
#include <bitset>
#pragma GCC optimize("unroll-loops")
#pragma GCC target("popcnt,tune=native")
template<int MIN_CHAR, int SIGMA, int MAX_LEN>
struct mutable_string_bitset {
std::vector<std::bitset<MAX_LEN>> occur;
template<typename InputIterator>
mutable_string_bitset(InputIterator first, InputIterator last) : occur(SIGMA) {
int i = 0;
for (InputIterator iter = first; iter != last; iter++)
occur[*iter - MIN_CHAR][i++] = true;
}
void assign(int i, int c) {
for (int a = 0; a < SIGMA; a++)
occur[a][i] = false;
occur[c - MIN_CHAR][i] = true;
}
/* Counts occurrences of the pattern [first, last) within the substring [L, R)
* O(|last - first| * MAX_LEN / MACHINE_WORD_SIZE)
*/
template<typename InputIterator>
int count_matches(InputIterator first, InputIterator last, int L = 0, int R = MAX_LEN) const {
static std::bitset<MAX_LEN> match;
match.set(); // sets all bits to true
int i = 0;
for (InputIterator iter = first; iter != last; iter++)
match &= occur[*iter - MIN_CHAR] >> (i++);
int count = 0;
int min_pos = L, max_pos = R - i + 1;
while (min_pos < max_pos && min_pos % 64)
count += match[min_pos++];
while (min_pos < max_pos && max_pos % 64)
count += match[--max_pos];
static uint64_t *data = (uint64_t*)&match;
for (int inx = min_pos / 64; inx < max_pos / 64; inx++)
count += __builtin_popcountll(data[inx]);
return count;
}
};