Pagini recente » Cod sursa (job #872415) | Cod sursa (job #1891112) | Cod sursa (job #1046672) | Cod sursa (job #969994) | Cod sursa (job #2341796)
#include <fstream>
#include <map>
#include <queue>
#include <string>
#include <vector>
using namespace std;
struct TrieNode
{
map<char, TrieNode*> sons;
TrieNode *father = nullptr;
TrieNode *suffix = nullptr;
int count = 0;
int index = -1;
string str = "";
TrieNode(TrieNode *father = nullptr) : father(father) {}
bool HasSon(char ch) const;
TrieNode* Son(char ch);
};
bool TrieNode::HasSon(char ch) const
{
return sons.count(ch) > 0;
}
TrieNode* TrieNode::Son(char ch)
{
auto it = sons.find(ch);
if (it != sons.end()) {
return it->second;
}
sons.insert({ch, new TrieNode(this)});
sons[ch]->str = this->str + string(1, ch);
return sons[ch];
}
void Insert(TrieNode *root, int index, const string &str, size_t pos = 0)
{
if (pos >= str.size()) {
root->index = index;
return;
}
Insert(root->Son(str[pos]), index, str, pos + 1);
}
TrieNode* FindSuffixNode(TrieNode *node, char ch)
{
if (!node->father->suffix) {
return node->father;
}
auto other = node->father->suffix;
while (other->suffix && !other->HasSon(ch)) {
other = other->suffix;
}
if (other->HasSon(ch)) {
other = other->Son(ch);
}
return other;
}
void BuildSuffixLinks(TrieNode *root)
{
queue<pair<char, TrieNode*>> q;
q.push({'\0', root});
while (!q.empty()) {
auto ch = q.front().first;
auto node = q.front().second;
q.pop();
if (ch != '\0') {
node->suffix = FindSuffixNode(node, ch);
}
for (const auto &p : node->sons) {
q.push({p.first, p.second});
}
}
}
void ExtractCount(TrieNode *root, vector<int> &count)
{
if (root->index >= 0) {
count[root->index] = root->count;
}
for (const auto &p : root->sons) {
ExtractCount(p.second, count);
}
}
vector<int> CountAppearances(int words, TrieNode *trie, const string &text)
{
TrieNode *node = trie;
for (const auto &ch : text) {
while (!node->HasSon(ch) && node->suffix) {
node = node->suffix;
}
if (node->HasSon(ch)) {
node = node->Son(ch);
}
auto it = node;
while (it) {
it->count += 1;
it = it->suffix;
}
}
vector<int> count(words, 0);
ExtractCount(trie, count);
return count;
}
int main()
{
ifstream fin("ahocorasick.in");
ofstream fout("ahocorasick.out");
string text;
getline(fin, text);
int words;
fin >> words;
fin.get();
TrieNode *trie = new TrieNode;
for (auto i = 0; i < words; i += 1) {
string word;
getline(fin, word);
Insert(trie, i, word);
}
BuildSuffixLinks(trie);
auto res = CountAppearances(words, trie, text);
for (const auto &count : res) {
fout << count << "\n";
}
return 0;
}