Pagini recente » Istoria paginii runda/tema_grf | Cod sursa (job #3203996) | Cod sursa (job #3283090) | Cod sursa (job #1763150) | Cod sursa (job #2680179)
#include <iostream>
#include <fstream>
#include <tuple>
#include <queue>
#include <vector>
#include <stack>
const int MAXLIT = 26;
const int MAXN = 101;
using namespace std;
ifstream in("ahocorasick.in");
ofstream out("ahocorasick.out");
struct Nod{
Nod *muchii[MAXLIT];
Nod *suffixLink;
int aparitii = 0;
Nod(){
suffixLink = nullptr;
for(int i = 0; i < MAXLIT; i++)
muchii[i] = nullptr;
}
};
class Trie{
public:
stack<Nod*>noduriInvers;
Trie(){
radacina = new Nod();
radacina->suffixLink = radacina;
}
void adauga(const string &sir){
Nod *nod = radacina;
for(char caracter : sir){
int poz = caracter - 'a';
if(nod->muchii[poz] != nullptr){
nod = nod->muchii[poz];
}else{
Nod *nou = new Nod();
// nou->s = nod->s + caracter;
nod->muchii[poz] = nou;
nod = nod->muchii[poz];
}
}
}
int numarAparitii(const string &sir){
Nod *nod = radacina;
for(char caracter : sir){
int poz = caracter - 'a';
nod = nod->muchii[poz];
}
return nod->aparitii;
}
void construiesteFailureLink(){
/// tuple de Nod, Tata si Caracter Curent
queue<tuple<Nod*,Nod*,char>>coada;
for(int i = 0; i < MAXLIT; i++)
if(radacina->muchii[i] != nullptr){
coada.push(make_tuple(radacina->muchii[i],radacina,'a' + i));
}
while(coada.size()){
auto it = coada.front();
Nod *curent = get<0>(it);
Nod *tata = get<1>(it);
char x = get<2>(it);
coada.pop();
noduriInvers.push(curent);
Nod *fail = tata->suffixLink;
while(fail->muchii[x - 'a'] == nullptr){
if(fail == radacina)
break;
fail = fail->suffixLink;
}
if(fail->muchii[x - 'a'] != nullptr && fail->muchii[x - 'a'] != curent){
curent->suffixLink = fail->muchii[x - 'a'];
}else
curent->suffixLink = radacina;
// cout<<curent->s<<" -> ";
// if(curent->suffixLink == radacina)
// cout<<"radacina"<<endl;
// else
// cout<<curent->suffixLink->s<<endl;
for(int i = 0; i < MAXLIT; i++){
if(curent->muchii[i] != nullptr){
coada.push(make_tuple(curent->muchii[i],curent,i + 'a'));
}
}
}
}
void rezolva(const string &input){
Nod *nod = radacina;
int index = 0;
for(char caracter : input){
int poz = caracter - 'a';
index++;
if(nod->muchii[poz] != nullptr){
nod = nod->muchii[poz];
// cout<<"sunt pe "<<nod->s<<endl;
nod->aparitii++;
}else{
while(nod->muchii[poz] == nullptr){
if(nod == radacina)
break;
nod = nod->suffixLink;
}
if(nod->muchii[poz] != nullptr){
nod = nod->muchii[poz];
nod->aparitii++;
}
}
}
}
void calculeazaAparitii(){
while(noduriInvers.size()){
Nod* nod = noduriInvers.top();
noduriInvers.pop();
for(int i = 0; i < MAXLIT; i++){
Nod *vecin = nod->muchii[i];
if(vecin != nullptr){
vecin->suffixLink->aparitii += vecin->aparitii;
}
}
}
}
void afisare(){
print(radacina);
}
private:
Nod *radacina;
void print(Nod *nod){
// cout<<nod->s<<" "<<nod->aparitii<<endl;
for(int i = 0; i < MAXLIT; i++){
if(nod->muchii[i] != nullptr){
print(nod->muchii[i]);
}
}
}
};
int main()
{
in.tie(0);
out.tie(0);
ios::sync_with_stdio(false);
string input;
int n;
in>>input>>n;
Trie *trie = new Trie();
vector<string>cuvinte(n);
for(int i = 0; i < n; ++i){
in>>cuvinte[i];
trie->adauga(cuvinte[i]);
}
trie->construiesteFailureLink();
trie->rezolva(input);
trie->calculeazaAparitii();
for(int i = 0; i < n; ++i)
out<<trie->numarAparitii(cuvinte[i])<<'\n';
return 0;
}