Pagini recente » Cod sursa (job #995955) | Cod sursa (job #2155127) | Cod sursa (job #924742) | Cod sursa (job #2944800) | Cod sursa (job #2877732)
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
ifstream f("ahocorasick.in");
ofstream g("ahocorasick.out");
const int SIGMA = 26;
class trie
{
private:
struct trieNode
{
int cnt;
vector < int > words;
trieNode* suffixLink;
trieNode* children[SIGMA];
trieNode();
};
trieNode* root;
int numberOfWords;
void clearTrie(trieNode*& node);
public:
trie();
~trie();
void insertKey(const string& key);
void computeSuffixLinks();
void query(const string& text);
};
trie :: trieNode :: trieNode()
{
cnt = 0;
suffixLink = NULL;
for (int i = 0; i < SIGMA; i++)
children[i] = NULL;
}
void trie :: clearTrie(trieNode*& node)
{
for (int i = 0; i < SIGMA; i++)
if (node -> children[i])
clearTrie(node -> children[i]);
delete node;
}
trie :: trie()
{
numberOfWords = 0;
root = new trieNode;
}
trie :: ~trie()
{
clearTrie(root);
}
void trie :: insertKey(const string& key)
{
trieNode* node = root;
for (int i = 0; i < key.size(); i++)
{
int index = key[i] - 'a';
if (!node -> children[index])
node -> children[index] = new trieNode;
node = node -> children[index];
}
numberOfWords++;
node -> words.push_back(numberOfWords);
}
void trie :: computeSuffixLinks()
{
queue < trieNode* > q;
for (int i = 0; i < SIGMA; i++)
if (root -> children[i])
{
root -> children[i] -> suffixLink = root;
q.push(root -> children[i]);
}
while (!q.empty())
{
trieNode* node = q.front();
q.pop();
for (int i = 0; i < SIGMA; i++)
if (node -> children[i])
{
trieNode* aux = node -> suffixLink;
while (aux && !aux -> children[i])
aux = aux -> suffixLink;
if (aux && aux -> children[i])
node -> children[i] -> suffixLink = aux -> children[i];
else
node -> children[i] -> suffixLink = root;
q.push(node -> children[i]);
}
}
}
void trie :: query(const string& text)
{
trieNode* node = root;
for (int i = 0; i < text.size(); i++)
{
int index = text[i] - 'a';
if (node -> children[index])
node = node -> children[index];
else
{
trieNode* aux = node -> suffixLink;
while (aux && !aux -> children[index])
aux = aux -> suffixLink;
if (aux && aux -> children[index])
node = aux -> children[index];
else
node = root;
}
node -> cnt++;
}
queue < trieNode* > q;
vector < trieNode* > antibfs;
q.push(root);
while (!q.empty())
{
trieNode* node = q.front();
q.pop();
antibfs.push_back(node);
for (int i = 0; i < SIGMA; i++)
if (node -> children[i])
q.push(node -> children[i]);
}
int* ans = new int[numberOfWords + 1];
reverse(antibfs.begin(), antibfs.end());
for (auto node : antibfs)
{
for (auto word : node -> words)
ans[word] = node -> cnt;
if (node -> suffixLink)
node -> suffixLink -> cnt += node -> cnt;
}
for (int i = 1; i <= numberOfWords; i++)
g << ans[i] << "\n";
delete[] ans;
}
int n;
string text;
trie T;
int main()
{
f >> text;
f >> n;
for (int i = 1; i <= n; i++)
{
string word; f >> word;
T.insertKey(word);
}
T.computeSuffixLinks();
T.query(text);
return 0;
}