Pagini recente » Cod sursa (job #2019208) | Cod sursa (job #2002254) | Cod sursa (job #483066) | Cod sursa (job #2702583) | Cod sursa (job #2810330)
#include <bits/stdc++.h>
using namespace std;
class Trie{
private:
static const int ALPHABET_SIZE = 26;
static const int FIRST_ELEM = 'a';
int matchCount;
Trie* suffixLink;
vector<Trie*> reverseSuffixLinks;
vector<Trie*> children;
vector<int> wordIndices;
void collectMatchCounts(Trie* node, vector<int>& counts){
for(Trie* nextNode: node->reverseSuffixLinks){
collectMatchCounts(nextNode, counts);
node->matchCount += nextNode->matchCount;
}
for(int wordIdx: node->wordIndices){
counts[wordIdx] += node->matchCount;
}
}
public:
Trie(){
matchCount = 0;
suffixLink = NULL;
children.assign(ALPHABET_SIZE, NULL);
}
void insert(const string& WORD, const int& WORD_IDX){
Trie* node = this;
for(char c: WORD){
int edgeID = c - FIRST_ELEM;
if(node->children[edgeID] == NULL){
node->children[edgeID] = new Trie();
}
node = node->children[edgeID];
}
node->wordIndices.push_back(WORD_IDX);
}
void createSuffixLinks(){
Trie* root = this;
queue<Trie*> q;
for(int edgeID = 0; edgeID < ALPHABET_SIZE; ++edgeID){
if(root->children[edgeID] != NULL){
root->children[edgeID]->suffixLink = root;
root->reverseSuffixLinks.push_back(root->children[edgeID]);
q.push(root->children[edgeID]);
}
}
while(!q.empty()){
Trie* node = q.front();
q.pop();
for(int edgeID = 0; edgeID < ALPHABET_SIZE; ++edgeID){
if(node->children[edgeID] != NULL){
Trie* tempNode = node->suffixLink;
while(tempNode != NULL && tempNode->children[edgeID] == NULL){
tempNode = tempNode->suffixLink;
}
if(tempNode == NULL){
node->children[edgeID]->suffixLink = root;
root->reverseSuffixLinks.push_back(node->children[edgeID]);
}else{
node->children[edgeID]->suffixLink = tempNode->children[edgeID];
tempNode->children[edgeID]->reverseSuffixLinks.push_back(node->children[edgeID]);
}
q.push(node->children[edgeID]);
}
}
}
}
void matchAllWords(const string& TEXT){
Trie* root = this;
Trie* node = root;
for(char c: TEXT){
int edgeID = c - FIRST_ELEM;
while(node != NULL && node->children[edgeID] == NULL){
node = node->suffixLink;
}
if(node == NULL){
node = root;
}else{
node = node->children[edgeID];
}
node->matchCount += 1;
}
}
void collectMatchCounts(vector<int>& counts){
fill(counts.begin(), counts.end(), 0);
collectMatchCounts(this, counts);
}
};
int main(){
ifstream cin("ahocorasick.in");
ofstream cout("ahocorasick.out");
string s;
cin >> s;
int n;
cin >> n;
Trie trie;
string word;
for(int i = 0; i < n; ++i){
cin >> word;
trie.insert(word, i);
}
trie.createSuffixLinks();
trie.matchAllWords(s);
vector<int> counts(n);
trie.collectMatchCounts(counts);
for(int i = 0; i < n; ++i){
cout << counts[i] << "\n";
}
cin.close();
cout.close();
return 0;
}