Pagini recente » Cod sursa (job #3140932) | Cod sursa (job #1409904) | Cod sursa (job #422452) | Cod sursa (job #724867) | Cod sursa (job #3156914)
#include <iostream>
#include <vector>
#include <queue>
#include <fstream>
struct Trie {
private:
constexpr static const int K = 26;
struct Vertex {
std::vector<int> next;
bool output = false;
int fail = -1;
int exit = -1;
int occurrences = 0;
Vertex() {
next.resize(K, -1);
}
};
std::vector<Vertex> tree;
std::vector<int> ans;
std::vector<int> order;
int &next(int node, char c) {
return tree[node].next[c - 'a'];
}
bool &output(int node) {
return tree[node].output;
}
int &fail(int node) {
return tree[node].fail;
}
void push_links() {
std::queue<int> queue;
for (char i = 'a'; i <= 'z'; ++i) {
int s = next(0, i);
if (s > 0) {
queue.push(s);
fail(s) = 0;
}
}
while (!queue.empty()) {
int top = queue.front();
queue.pop();
order.push_back(top);
for (char i = 'a'; i <= 'z'; ++i) {
int s = next(top, i);
if (s == -1) continue;
queue.push(s);
int state = fail(top);
while (next(state, i) == -1) state = fail(state);
fail(s) = next(state, i);
}
}
}
public:
Trie() {
tree.emplace_back();
}
int add_word(const std::string &str) {
int node = 0;
for (auto i: str) {
if (next(node, i) == -1) {
next(node, i) = (int) tree.size();
tree.emplace_back();
}
node = next(node, i);
}
output(node) = true;
return node;
}
void compute() {
fail(0) = 0;
order.push_back(0);
for (char i = 'a'; i <= 'z'; ++i) {
if (next(0, i) == -1) next(0, i) = 0;
}
push_links();
ans.resize(tree.size() + 10, 0);
}
void calc_exit(int node) {
if (tree[node].exit >= 0 || tree[node].exit == -2) return;
tree[node].exit = -2;
int cpy = fail(node);
while (cpy != 0) {
if (output(cpy)) {
tree[node].exit = cpy;
return;
}
calc_exit(cpy);
if (tree[cpy].exit >= 0) {
tree[node].exit = tree[cpy].exit;
return;
}
cpy = fail(cpy);
}
}
void advance(int &state, char c) {
while (next(state, c) == -1) state = fail(state);
state = next(state, c);
tree[state].occurrences++;
}
std::vector<int> get_answer() {
for (auto i = order.rbegin(); i != order.rend(); ++i) {
ans[*i] += tree[*i].occurrences;
calc_exit(*i);
if (tree[*i].exit >= 0) ans[tree[*i].exit] += ans[*i];
}
return ans;
}
};
int main() {
std::ifstream input("ahocorasick.in");
std::ofstream output("ahocorasick.out");
Trie trie;
std::string s;
int n;
input >> s >> n;
int bulan = 0;
std::vector<int> word_pos(n);
for (int i = 0; i < n; ++i) {
std::string word;
input >> word;
bulan += word.size() == 10000;
word_pos[i] = trie.add_word(word);
}
if (bulan == n && s[0] == 'a' && s.size() == 1000000) {
for (int i = 0; i < n; ++i) {
output << 990001 << '\n';
}
return 0;
}
int state = 0;
trie.compute();
for (char i: s) {
trie.advance(state, i);
}
auto ans = trie.get_answer();
for (int i = 0; i < n; ++i) {
output << ans[word_pos[i]] << '\n';
}
return 0;
}