Pagini recente » Cod sursa (job #2275980) | Cod sursa (job #1257841) | Cod sursa (job #168229) | Cod sursa (job #2028731) | Cod sursa (job #2724552)
#include <fstream>
#include <queue>
using namespace std;
class Node {
public:
Node* children[26];
Node* suffix;
Node* output;
Node* parent;
bool is_pattern;
char ch;
int occ;
Node() : children(), suffix(), output(), parent(), is_pattern(), ch(), occ() {}
};
class Trie {
public:
Node* root;
Trie() : root(new Node) {}
void insert(string s) {
Node* crt = root;
for (auto ch : s) {
if (!crt->children[ch - 'a'])
crt->children[ch - 'a'] = new Node;
crt->children[ch - 'a']->parent = crt;
crt->children[ch - 'a']->ch = ch;
crt = crt->children[ch - 'a'];
}
crt->is_pattern = true;
}
void build_suffix_links() {
queue<Node*> q;
for (int i = 0; i < 26; ++i)
if (root->children[i]) {
root->children[i]->suffix = root;
q.push(root->children[i]);
}
while (!q.empty()) {
Node* crt = q.front();
q.pop();
for (int i = 0; i < 26; ++i)
if (crt->children[i])
q.push(crt->children[i]);
Node* s = crt->parent->suffix;
while (s && !s->children[crt->ch - 'a'])
s = s->suffix;
if (s)
crt->suffix = s->children[crt->ch - 'a'];
else
crt->suffix = root;
}
}
void build_output_links() {
queue<Node*> q;
for (int i = 0; i < 26; ++i)
if (root->children[i])
q.push(root->children[i]);
while (!q.empty()) {
Node* crt = q.front();
q.pop();
for (int i = 0; i < 26; ++i)
if (crt->children[i])
q.push(crt->children[i]);
Node* s = crt->suffix;
if (s->is_pattern)
crt->output = s;
else
crt->output = s->output;
}
}
void build() {
build_suffix_links();
build_output_links();
}
void run(string s) {
Node* crt = root;
for (auto ch : s) {
if (crt->children[ch - 'a'])
crt = crt->children[ch - 'a'];
else {
while (crt != root) {
crt = crt->suffix;
if (crt->children[ch - 'a']) {
crt = crt->children[ch - 'a'];
break;
}
}
}
Node* o;
if (crt->is_pattern)
o = crt;
else
o = crt->output;
while (o) {
++o->occ;
o = o->output;
}
}
}
int count_occ(string s) {
Node* crt = root;
for (auto ch : s)
crt = crt->children[ch - 'a'];
return crt->occ;
}
};
const int N = 100;
string txt, pat[N];
Trie t;
int main() {
ifstream in("ahocorasick.in");
ofstream out("ahocorasick.out");
int n;
in >> txt >> n;
for (int i = 0; i < n; ++i) {
in >> pat[i];
t.insert(pat[i]);
}
t.build();
t.run(txt);
for (int i = 0; i < n; ++i)
out << t.count_occ(pat[i]) << '\n';
in.close();
out.close();
return 0;
}