Pagini recente » Cod sursa (job #3274388) | Cod sursa (job #371205) | Istoria paginii runda/winter2020 | Istoria paginii runda/jc2018-runda-2 | Cod sursa (job #3242705)
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
ifstream cin("ahocorasick.in");
ofstream cout("ahocorasick.out");
const int MAXN = 1000000 + 10; // Maximum number of nodes in the trie
const int ALPHABET_SIZE = 26; // For lowercase English letters
struct Node {
int next[ALPHABET_SIZE]; // Children nodes
int fail; // Failure link
vector<int> outputs; // Indices of patterns ending at this node
Node() {
memset(next, -1, sizeof(next));
fail = 0;
}
};
vector<Node> trie;
vector<int> counts; // Counts of each pattern
vector<string> patterns;
void insert_pattern(const string& pattern, int index) {
int node = 0;
for (char ch : pattern) {
int c = ch - 'a';
if (trie[node].next[c] == -1) {
trie[node].next[c] = trie.size();
trie.emplace_back();
}
node = trie[node].next[c];
}
trie[node].outputs.push_back(index);
}
void build_failure_links() {
queue<int> q;
// Initialize failure links for immediate children of root
for (int c = 0; c < ALPHABET_SIZE; ++c) {
int child = trie[0].next[c];
if (child != -1) {
trie[child].fail = 0;
q.push(child);
} else {
trie[0].next[c] = 0; // Optimization to avoid checking for -1 during search
}
}
// BFS to build failure links
while (!q.empty()) {
int rnode = q.front();
q.pop();
for (int c = 0; c < ALPHABET_SIZE; ++c) {
int child = trie[rnode].next[c];
if (child != -1) {
int fnode = trie[rnode].fail;
while (trie[fnode].next[c] == -1) {
fnode = trie[fnode].fail;
}
trie[child].fail = trie[fnode].next[c];
trie[child].outputs.insert(trie[child].outputs.end(),
trie[trie[child].fail].outputs.begin(),
trie[trie[child].fail].outputs.end());
q.push(child);
}
}
}
}
void search_in_text(const string& text) {
int node = 0;
for (char ch : text) {
int c = ch - 'a';
while (trie[node].next[c] == -1) {
node = trie[node].fail;
}
node = trie[node].next[c];
for (int pattern_index : trie[node].outputs) {
counts[pattern_index]++;
}
}
}
int main() {
// Read the text
string text;
cin >> text;
// Read the number of patterns
int n;
cin >> n;
patterns.resize(n);
counts.resize(n, 0);
trie.emplace_back(); // Root node
// Read and insert patterns into trie
for (int i = 0; i < n; ++i) {
cin >> patterns[i];
insert_pattern(patterns[i], i);
}
// Build failure links
build_failure_links();
// Search patterns in text
search_in_text(text);
// Output the counts
for (int i = 0; i < n; ++i) {
cout << counts[i] << '\n';
}
return 0;
}