Pagini recente » Cod sursa (job #481324) | Cod sursa (job #2779671) | Cod sursa (job #2645649) | Cod sursa (job #1299342) | Cod sursa (job #2286781)
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <queue>
using namespace std;
inline int toInt(char x)
{
return x - 'a';
}
struct Trie
{
Trie()
{
fail = nullptr;
ap = 0;
for(int i = 0; i < 26; ++i)
child[i] = nullptr;
}
Trie* Insert(const char * s)
{
if(s[0] == '\0')
return this;
int c = toInt(s[0]);
if(child[c] == nullptr)
child[c] = new Trie();
return child[c]->Insert(s+1);
}
void AddChildAps()
{
for(auto c:failChild)
{
c->AddChildAps();
ap += c->ap;
}
}
void ResetAp()
{
for(int i = 0; i < 26; ++i)
if(child[i])
child[i]->ResetAp();
ap = 0;
}
Trie * child[26];
Trie * fail;
vector<Trie*> failChild;
int ap;
};
class Aho
{
public:
Aho(const vector<string> &v)
{
trie = new Trie;
nodCuv.resize(v.size());
for(int i = 0; i < v.size(); ++i)
nodCuv[i] = trie->Insert(v[i].c_str());
BFS();
}
vector<int> GetAp(const string &text)
{
Trie * current = trie;
for(auto c:text)
{
while(current && !current->child[toInt(c)])
current = current->fail;
if(!current)
current = trie;
else
current = current->child[toInt(c)];
current->ap++;
}
trie->AddChildAps();
vector<int> ret(nodCuv.size());
for(int i = 0; i < ret.size(); ++i)
ret[i] = nodCuv[i]->ap;
trie->ResetAp();
return ret;
}
private:
Trie * trie;
vector<Trie*> nodCuv;
void BFS()
{
queue<Trie*> q;
q.push(trie);
Trie * nod, * current;
while(q.empty() == false)
{
nod = q.front();
q.pop();
for(int i = 0; i < 26; ++i)
if(nod->child[i])
{
current = nod->fail;
while(current && !current->child[i])
current = current->fail;
if(!current)
current = trie;
else
current = current->child[i];
nod->child[i]->fail = current;
current->failChild.push_back(nod->child[i]);
q.push(nod->child[i]);
}
}
}
};
int main()
{
ifstream in("ahocorasick.in");
string s;
in >> s;
int n;
in >> n;
vector<string> v(n);
for(int i = 0; i < n; ++i)
in >> v[i];
in.close();
Aho aho(v);
vector<int> rasp = aho.GetAp(s);
ofstream out("ahocorasick.out");
for(auto x:rasp)
out << x << "\n";
out.close();
return 0;
}