Pagini recente » Cod sursa (job #2974023) | Cod sursa (job #523884) | Cod sursa (job #2339594) | Cod sursa (job #2627586) | Cod sursa (job #3299553)
#include<bits/stdc++.h>
using namespace std;
//#pragma GCC optimize("O3,unroll-loops")
//#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
string numeFisier="ahocorasick";
ifstream fin(numeFisier+".in"); ofstream fout(numeFisier+".out");
#define cin fin
#define cout fout
#define INIT ios_base :: sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define mp make_pair
#define pb push_back
#define ft first
#define sc second
#define ll long long
#define pii pair<int, int>
#define count_bits __builtin_popcount
//#define int ll
int t, n, m, k, a[300010], q, l, r;
string text;
string pattern[101];
int occurrences[101];
class AhoCorasickAutomaton{
public:
class Vertex{
public:
Vertex* suffLink=nullptr;
Vertex* pchr[26];
vector<int> wordIndexes;
int lazy=0;
Vertex* exitLink=nullptr;
bool checkedExit = false;
int inDegree = 0;
};
// set<Vertex*> s;
// map<Vertex*, int> h;
Vertex *root = new Vertex();
void addWordTrie(Vertex* Root,string s, int index){
Vertex* node = Root;
for(int i=0; i<s.length(); i++){
auto parent = node;
if( !node->pchr[ s[i] - 'a' ] ){
node->pchr[ s[i] - 'a' ] = new Vertex();
node->pchr[ s[i]-'a' ]->suffLink=root;
}
node = node->pchr[ s[i]-'a' ];
}
node->wordIndexes.pb(index);
}
void makeSuffixLinks(Vertex* root, int depth){
// int sz = s.size();
// s.insert(root);
// if(s.size()>sz){
// h[root] = s.size();
// }
for(char c='a'; c<='z'; c++){
if( !root->pchr[ c-'a' ] )continue;
if(depth>0){
Vertex* node = root->pchr[c-'a'];
node->suffLink = root->suffLink;
while( !node->suffLink->pchr[ c - 'a' ] && (node->suffLink->suffLink != node->suffLink) ){
node->suffLink = node->suffLink->suffLink;
}
if( node->suffLink->pchr[ c-'a' ] ){
node->suffLink = node->suffLink->pchr[ c-'a' ];
}
}
makeSuffixLinks( root->pchr[c-'a'], depth+1 );
}
}
void dfsSuffixLinks(Vertex* root){
auto node = root;
if(root->checkedExit){
return;
}
if(!node->suffLink->checkedExit){
dfsSuffixLinks(node->suffLink);
}
node->checkedExit=true;
node->exitLink = node->suffLink->exitLink;
if(!node->suffLink->wordIndexes.empty()){
node->exitLink = node->suffLink;
}
}
void makeExitLink(Vertex * root){
dfsSuffixLinks(root);
for(char c='a'; c<='z'; c++){
if( !root->pchr[ c-'a' ] )continue;
makeExitLink( root->pchr[c-'a'] );
}
// cout<<h[root]<<": "<<h[root->suffLink]<<" - "<<h[root->exitLink]<<" - ";
// for(char c='a'; c<='z'; c++){
// if( root->pchr[c-'a' ] ){
// cout<<"("<<c<<" + "<<h[root->pchr[c-'a']]<<") ";
// }
// }
// cout<<"\n";
}
void propagateLazy(){
queue<Vertex*> q;
stack<Vertex*> s;
s.push(root);
while(!s.empty()){
auto node = s.top();
if( !node->wordIndexes.empty() ){
if(node->exitLink){
node->exitLink->inDegree++;
}
q.push(node);
}
s.pop();
for(char c='a' ;c<='z'; c++){
if( node->pchr[c-'a'] ){
s.push(node->pchr[ c-'a' ]);
}
}
}
while(!q.empty()){
auto f = q.front();
q.pop();
if(f->inDegree>0){
continue;
}
if(f->exitLink){
f->exitLink->lazy+=f->lazy+((int)f->wordIndexes.size());
f->exitLink->inDegree--;
if(f->exitLink->inDegree==0){
q.push(f->exitLink);
}
}
for(auto index:f->wordIndexes){
occurrences[index]+=f->lazy;
}
f->lazy=0;
}
}
void searchText(string &text, int occurrences[]){
Vertex* node = root;
for(int i=0; i<text.length(); i++){
char c = text[i];
if( node->pchr[ c-'a' ] ){
node = node->pchr[ c-'a' ];
}
else{
while( !node->pchr[ c - 'a' ] && node->suffLink!=node ){
node = node->suffLink;
}
if(node->pchr[ c-'a' ]){
node = node->pchr[c-'a'];
}
}
for(auto index:node->wordIndexes){
occurrences[index]++;
}
if( node->wordIndexes.empty() ){
if( node->exitLink ){
node->exitLink->lazy++;
}
}
}
propagateLazy();
}
} ahoCorasick;
int32_t main(){
INIT
cin>>text;
cin>>k;
for(int i=1; i<=k; i++){
cin>>pattern[i];
}
ahoCorasick.root->suffLink = ahoCorasick.root;
ahoCorasick.root->checkedExit = true;
for(int i=1; i<=k; i++){
ahoCorasick.addWordTrie(ahoCorasick.root, pattern[i], i);
}
ahoCorasick.makeSuffixLinks(ahoCorasick.root, 0);
ahoCorasick.makeExitLink(ahoCorasick.root);
ahoCorasick.searchText(text, occurrences);
for(int i=1; i<=k; i++){
cout<<occurrences[i]<<"\n";
}
return 0;
}