Pagini recente » Cod sursa (job #1556537) | Cod sursa (job #624942) | Cod sursa (job #967561) | Cod sursa (job #605380) | Cod sursa (job #2760543)
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <memory.h>
using namespace std;
class Trie {
public:
Trie() {
memset(sons, 0, sizeof(sons));
failLink = 0;
frequency = 0;
}
void add(string s, int position, vector<Trie*> &indexToNode) {
_add(s, position, 0, indexToNode);
}
Trie *getSon(int index) {
return sons[index];
}
Trie *getFailLink() {
return failLink;
}
const vector<int>& getActiveSons() {
return activeSons;
}
void setFailLink(Trie *fail) {
failLink = fail;
}
void addFrequency(int k) {
frequency += k;
}
int getFrequency() {
return frequency;
}
private:
void _add(string &s, int position, int index, vector<Trie*> &indexToNode) {
if (index == s.size()) {
indexToNode[position] = this;
return;
}
int childPos = s[index] - 'a';
if (sons[childPos] == 0) {
sons[childPos] = new Trie();
activeSons.emplace_back(childPos);
}
sons[childPos]->_add(s, position, index + 1, indexToNode);
}
Trie *sons[26]; // representing the prefix tree
Trie *failLink; // pointer to the longest prefix in the trie which is also suffix.
int frequency;
vector<int> activeSons;
};
class AhoCorasick {
public:
AhoCorasick(int size): indexToNode(size, 0), dictionarySize(size) {
root = new Trie();
root->setFailLink(root);
}
void add(string s, int position) {
root->add(s, position, indexToNode);
}
void buildFailLinks() {
for (auto index: root->getActiveSons()) {
Trie *son = root->getSon(index);
son->setFailLink(root);
Q.emplace_back(son);
}
Trie *curr;
int pz = 0;
while (pz < Q.size()) {
curr = Q[pz++];
for (auto index: curr->getActiveSons()) {
Trie *son = curr->getSon(index);
Trie *fail = curr->getFailLink();
Trie *extension = fail->getSon(index);
while (true) {
if (extension) {
// we managed to extend the previous longest prefix
son->setFailLink(extension);
break;
}
if (fail == root) {
// we didn't manage to extend any of the previous longest prefixes.
son->setFailLink(root);
break;
}
fail = fail->getFailLink();
extension = fail->getSon(index);
}
Q.emplace_back(son);
}
}
}
void digest(string s)
{
int pos = 0;
Trie *crt = root;
while (pos < s.size()) {
int index = s[pos] - 'a';
if (crt->getSon(index)) {
crt = crt->getSon(index);
crt->addFrequency(1);
++pos;
continue;
}
if (crt == root) {
++pos;
continue;
}
crt = crt->getFailLink();
}
for (;Q.size(); Q.pop_back())
Q.back()->getFailLink()->addFrequency(Q.back()->getFrequency());
}
int getFrequencyByIndex(int wordIndex) {
return indexToNode[wordIndex]->getFrequency();
}
private:
int dictionarySize;
Trie *root;
vector<Trie*> indexToNode;
vector<Trie*> Q;
};
int main()
{
ifstream fin("ahocorasick.in");
ofstream fout("ahocorasick.out");
fin.sync_with_stdio(false);
fin.tie(0);
string s, word;
int N;
fin >> s >> N;
AhoCorasick *automaton = new AhoCorasick(N);
for (int i = 0; i < N; ++i) {
fin >> word;
automaton->add(word, i);
}
automaton->buildFailLinks();
automaton->digest(s);
for (int i = 0; i < N; ++i)
fout << automaton->getFrequencyByIndex(i) << "\n";
return 0;
}