Pagini recente » Cod sursa (job #1780023) | Cod sursa (job #892304) | Cod sursa (job #929600) | Cod sursa (job #2460174) | Cod sursa (job #2426497)
#include <vector>
#include <fstream>
#include <cstring>
struct nod_trie {
int nr_in;
std::vector<int> list_edge;
nod_trie *next_chr[31], *link_fail;
nod_trie () {
link_fail = NULL;
nr_in = 0;
std::memset(next_chr, 0, sizeof next_chr);
}
};
template <typename the_type> class automat_aho_coarasick {
private:
the_type *root;
int nr_words = 0;
std::vector<the_type*> sign_at;
public:
automat_aho_coarasick () {
root = new nod_trie();
nr_words = 0;
}
void recursive_deiteration(the_type *this_node) {
for (unsigned int i = 0; i < 31; ++i) {
if (this_node -> next_chr[i])
recursive_deiteration(this_node -> next_chr[i]);
}
delete this_node;
return;
}
~automat_aho_coarasick() {
recursive_deiteration(root);
}
int get_idx (char c) {
int idx_next = 0;
if ('a' <= c && c <= 'z')
idx_next = c - 'a';
else {
if (c == ':')
idx_next = 'z' - 'a' + 1;
if (c == '\\')
idx_next = 'z' - 'a' + 2;
if (c == '.')
idx_next = 'z' - 'a' + 3;
if (c == '_')
idx_next = 'z' - 'a' + 4;
}
return idx_next;
}
void add_in_trie (const std::string &word) {
the_type *next_nod = root;
int idx_next;
for (unsigned int i = 0; i < word.length(); ++i) {
idx_next = get_idx(word[i]);
if (next_nod->next_chr[idx_next] == 0)
next_nod->next_chr[idx_next] = new nod_trie();
next_nod = next_nod->next_chr[idx_next];
}
++nr_words;
next_nod->list_edge.push_back(nr_words);
}
void build_automat () {
root -> link_fail = root;
sign_at.clear();
sign_at.push_back(root);
for (unsigned int i = 0; i < sign_at.size(); ++i) {
for (unsigned int j = 0; j < 31; ++j) {
if (sign_at[i]->next_chr[j] != 0) {
sign_at.push_back(sign_at[i]->next_chr[j]);
the_type *from = sign_at[i]->link_fail;
while (from != root && from->next_chr[j] == 0)
from = from->link_fail;
if (sign_at[i] != root && from->next_chr[j] != 0)
sign_at[i]->next_chr[j]->link_fail = from->next_chr[j];
else
sign_at[i]->next_chr[j]->link_fail = root;
}
}
}
}
std::vector<int> check_string(std::string str) {
the_type *check_nod = root;
int idx_next;
std::vector<int> nr_found;
nr_found.resize(nr_words + 1);
for (unsigned int i = 0; i < str.length(); ++i) {
idx_next = get_idx(str[i]);
while (check_nod->next_chr[idx_next] == 0 &&
check_nod != root)
check_nod = check_nod->link_fail;
if (check_nod->next_chr[idx_next])
check_nod = check_nod->next_chr[idx_next];
++check_nod->nr_in;
}
int bound = sign_at.size() - 1;
for (unsigned int i = bound; i > 0; --i) {
check_nod = sign_at[i];
check_nod->link_fail->nr_in += check_nod->nr_in;
int cnt = check_nod->list_edge.size();
for (int j = 0; j < cnt; ++j)
nr_found[check_nod->list_edge[j]] = check_nod->nr_in;
}
return nr_found;
}
};
int main() {
std::ifstream fin("ahocorasick.in");
std::ofstream fout("ahocorasick.out");
std::string sir;
int n;
automat_aho_coarasick<nod_trie> solver;
std::string cuvinte;
std::vector<int> sol;
fin >> sir;
fin >> n;
for (int i = 0; i < n; ++i) {
fin >> cuvinte;
solver.add_in_trie(cuvinte);
}
solver.build_automat();
sol = solver.check_string(sir);
for (int i = 1; i < sol.size(); ++i) {
fout << sol[i] << "\n";
}
return 0;
}