Pagini recente » Cod sursa (job #2548895) | Cod sursa (job #3127008) | Cod sursa (job #2689815) | Cod sursa (job #351729) | Cod sursa (job #2002752)
#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:
int group;
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, nro;
vector<vector<int>> wordsFromGroup;
vector<int> groupCnt;
int main()
{
fin >> text;
fin >> M;
cnt = vector<int>(M + 1);
groupCnt.push_back(0);
wordsFromGroup.push_back(vector<int>());
for ( int i = 0; i < M; ++i )
{
fin >> Trie::s; ++nro;
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 < wordsFromGroup.size(); ++i )
for ( const int& x : wordsFromGroup[i] )
cnt[x] += groupCnt[i];
for ( int i = 1; i <= M; ++i )
fout << cnt[i] << '\n';
fin.close();
fout.close();
return 0;
}
Trie::Trie()
{
group = 0;
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() )
{
if ( group == 0 )
{
group = ++nr;
wordsFromGroup.push_back(vector<int>());
groupCnt.push_back(0);
}
wordsFromGroup[group].push_back(nro);
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;
if ( node != root && node->blueEdge == nullptr )
node->MakeBlueEdges();
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->group )
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 ( group > 0 )
groupCnt[group]++;
auto greens = greenEdge;
while ( greens != nullptr )
{
groupCnt[greens->group]++;
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);
}
}
}