Pagini recente » Cod sursa (job #3219664) | Cod sursa (job #3219483) | Cod sursa (job #738584) | Cod sursa (job #694724) | Cod sursa (job #2002727)
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream fin("ahocorasick.in");
ofstream fout("ahocorasick.out");
class Trie{
public:
static string s;
Trie();
void AddWord( int pos ); // only after adding all the words I must make blue and green edges
void MakeBlueEdges();
void MakeGreenEdges();
void _MakeGreenEdges();
void Solve( int pos );
private:
vector<int> word; // is this the end of a word from the dictionary?
Trie *sons[26];
Trie *blueEdge, *greenEdge;
Trie *parent;
char letter;
bool hasGreen;
};
Trie *root = new Trie();
string Trie::s = "";
string text;
int N, M;
vector< pair<int, int> > sol;
vector<int> cnt;
int nr;
int main()
{
fin >> text;
fin >> M;
cnt = vector<int>(M + 1);
for ( int i = 0; i < M; ++i )
{
++nr;
fin >> Trie::s;
N = Trie::s.size();
root->AddWord(0);
}
root->MakeBlueEdges();
root->MakeGreenEdges();
Trie::s = text;
N = text.size();
root->Solve(0);
for ( int i = 1; i <= M; ++i )
fout << cnt[i] << '\n';
fin.close();
fout.close();
return 0;
}
Trie::Trie()
{
word = vector<int>();
for ( int i = 0; i < 26; ++i )
sons[i] = nullptr;
blueEdge = greenEdge = parent = nullptr;
letter = 'a';
hasGreen = true;
}
void Trie::AddWord( int p )
{
if ( p == Trie::s.size() )
{
word.push_back(nr);
return;
}
int pos = s[p] - 'a';
if ( sons[pos] == nullptr )
{
sons[pos] = new Trie();
sons[pos]->letter = s[p];
sons[pos]->parent = this;
}
sons[pos]->AddWord(p + 1);
}
void Trie::MakeBlueEdges()
{
if ( this != root )
{
int p = letter - 'a';
auto node = parent;
while ( node != root && node->blueEdge->sons[p] == nullptr )
{
node = node->blueEdge;
if ( node->blueEdge == nullptr )
node->MakeBlueEdges();
}
if ( node != root )
blueEdge = node->blueEdge->sons[p] != nullptr
&& node->blueEdge->sons[p] != this ? node->blueEdge->sons[p] : root;
else
blueEdge = root->sons[p] != nullptr && root->sons[p] != this ? root->sons[p] : root;
}
for ( int i = 0; i < 26; ++i )
if ( sons[i] != nullptr && sons[i]->blueEdge == nullptr )
sons[i]->MakeBlueEdges();
}
void Trie::MakeGreenEdges()
{
for ( int i = 0; i < 26; ++i )
if ( sons[i] != nullptr )
sons[i]->_MakeGreenEdges();
}
void Trie::_MakeGreenEdges()
{
if ( this == root || greenEdge != nullptr || !hasGreen )
return;
if ( blueEdge->word.size() )
greenEdge = blueEdge;
else
{
if ( blueEdge->greenEdge == nullptr )
blueEdge->_MakeGreenEdges();
if ( blueEdge != root && blueEdge->greenEdge != nullptr )
greenEdge = blueEdge->greenEdge;
else
hasGreen = false;
}
for ( int i = 0; i < 26; ++i )
if ( sons[i] != nullptr && sons[i]->greenEdge == nullptr )
sons[i]->_MakeGreenEdges();
}
void Trie::Solve( int pos )
{
if ( pos > N )
return;
if ( this == root )
{
int l = Trie::s[pos] - 'a';
if ( sons[l] == nullptr )
this->Solve(pos + 1);
else
sons[l]->Solve(pos + 1);
}
else
{
if ( word.size() > 0 )
for ( const int W : word )
++cnt[W];
auto greens = greenEdge;
while ( greens != nullptr )
{
for ( const int W : greens->word )
++cnt[W];
greens = greens->greenEdge;
}
if ( pos < N )
{
int l = Trie::s[pos] - 'a';
auto curr = this;
while ( curr != root && curr->sons[l] == nullptr )
curr = curr->blueEdge;
if ( curr->sons[l] != nullptr )
curr->sons[l]->Solve(pos + 1);
else
root->Solve(pos + 1);
}
}
}