Pagini recente » Cod sursa (job #2184386) | Cod sursa (job #1048765) | Cod sursa (job #282417) | Cod sursa (job #571072) | Cod sursa (job #2810313)
#include <bits/stdc++.h>
using namespace std;
class Trie{
private:
static const int ALPHABET_SIZE = 26;
static const int FIRST_ELEM = 'a';
int terminalNodeCount;
int matchCount;
Trie* suffixLink;
vector<Trie*> reverseSuffixLinks;
Trie* children[ALPHABET_SIZE];
void updateMatchCounts(Trie* node){
for(Trie* nextNode: node->reverseSuffixLinks){
updateMatchCounts(nextNode);
node->matchCount += nextNode->matchCount;
}
}
public:
Trie(){
terminalNodeCount = 0;
matchCount = 0;
suffixLink = NULL;
reverseSuffixLinks.clear();
fill(children, children + ALPHABET_SIZE, (Trie*)NULL);
}
void insert(const string& WORD){
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->terminalNodeCount += 1;
}
void insertAllWords(const vector<string>& WORDS){
for(const string& WORD: WORDS){
insert(WORD);
}
}
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 != root && tempNode->children[edgeID] == NULL){
tempNode = tempNode->suffixLink;
}
if(tempNode->children[edgeID] == 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 updateMatchCounts(){
updateMatchCounts(this);
}
int getMatchCount(const string& WORD){
Trie* node = this;
for(char c: WORD){
int edgeID = c - FIRST_ELEM;
if(node->children[edgeID] == NULL){
return 0;
}
node = node->children[edgeID];
}
return node->matchCount;
}
};
int main(){
ifstream cin("ahocorasick.in");
ofstream cout("ahocorasick.out");
string s;
cin >> s;
int n;
cin >> n;
vector<string> words(n);
for(int i = 0; i < n; ++i){
cin >> words[i];
}
Trie trie;
trie.insertAllWords(words);
trie.createSuffixLinks();
trie.matchAllWords(s);
trie.updateMatchCounts();
for(int i = 0; i < n; ++i){
cout << trie.getMatchCount(words[i]) << "\n";
}
cin.close();
cout.close();
return 0;
}