Pagini recente » Cod sursa (job #2111921) | Cod sursa (job #2009565) | Cod sursa (job #941688) | Cod sursa (job #2073834) | Cod sursa (job #98488)
Cod sursa(job #98488)
// chestii grele
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
#define RUN_IT
using namespace std;
int N, M, L, ret;
char A[10111111], cuv[50111][22];
clock_t start, end;
void clock_it( string x )
{
#ifndef RUN_IT
clock_t at = clock();
cout << x << " = " << 1.0 * ( at - start ) / CLOCKS_PER_SEC << endl;
#endif
}
class Trie
{
#define V 4
public:
int ID_POOL;
class node
{
public:
int id;
char term;
node * to[ V ];
node()
{
for( int i = 0; i < V; ++i )
to[i] = NULL;
id = -1;
term = 0;
}
} * R;
Trie()
{
R = new node();
R->id = 0;
ID_POOL = 1;
}
void add_dict( vector<string> w )
{
for( int i = 0; i < (int)w.size(); ++i )
add_word( w[i] );
}
void add_word( string w )
{
// cout << "-> " << w << endl;
node * at = R;
for( int i = 0; i < (int)w.size(); ++i )
{
if( at->to[ w[i] ] )
at = at->to[ w[i] ];
else
{
node * n = new node();
n->id = ID_POOL++;
at->to[ w[i] ] = n;
at = n;
}
}
at->term = 1;
}
void print_trie( node * n, int pos)
{
int nr(0);
for( int x = 0; x < V; ++x )
if( n->to[x] )
{
if( nr )
cout << string( pos, ' ' );
cout << (char)(x);
print_trie( n->to[x], pos + 1 );
++nr;
}
if( !nr )
cout << endl;
}
};
#define MAX_SZ (1<<20)
int f[MAX_SZ], out[MAX_SZ];
int g[MAX_SZ][V];
queue<int> Q;
Trie T;
class AC
{
#define V 4
private:
int nr_word, nr_state;
// vector<int> f, out;
// vector< vector<int> > g;
public:
AC()
{
nr_word = 0;
}
void add_word( string w )
{
T.add_word( w );
}
void add_dict( vector<string> w )
{
T.add_dict( w );
}
void debug()
{
T.print_trie( T.R, 0 );
}
void df( Trie::node * n )
{
for( int x = 0; x < V; x++ )
{
if( n->to[x] )
{
g[ n->id ][ x ] = n->to[x]->id;
df( n->to[x] );
}
else
{
if( n->id == 0 ) // root
g[ 0 ][ x ] = 0;
else
g[ n->id ][ x ] = -1;
}
}
out[ n->id ] = n->term;
}
void build_automata()
{
nr_state = T.ID_POOL;
// cout << " ! " << nr_state << endl; exit(0);
// f.resize( nr_state ), out.resize( nr_state );
// g.resize( nr_state );
// for( int i = 0; i < nr_state; ++i )
// g[i].resize( V );
clock_it( "Resizing" );
df( T.R );
clock_it( "df" );
for( int x = 0; x < V; ++x )
if( T.R->to[x] )
f[ T.R->to[x]->id ] = 0,
Q.push( T.R->to[x]->id );
clock_it( "graph" );
while( (int)Q.size() )
{
int r = Q.front(), u, v; Q.pop();
for( int x = 0; x < V; ++x )
if( (u=g[ r ][ x ]) != -1 ) // u is the son of r with edge x
{
Q.push( u );
v = f[ r ];
while( g[ v ][ x ] == -1 )
v = f[ v ];
f[ u ] = g[ v ][ x ];
out[ u ] |= out[ f[u] ];
}
}
clock_it( "queue" );
}
inline int process_character( int & q, char x )
{
while( g[ q ][ x ] == -1 )
q = f[ q ];
q = g[ q ][ x ];
return out[ q ];
}
int process_string()
{
int q = 0, nr_found = 0, op;
for( int i = 0; i < L; ++i )
{
while( g[ q ][ A[i] ] == -1 )
q = f[ q ];
q = g[ q ][ A[i] ];
// cout << "pos : " << i << " found " << v << endl;
nr_found += out[q];
}
return nr_found;
}
} MyAC;
void gen()
{
freopen("abc2.in", "w", stdout);
L = 10000000, N = 50000, M = 20;
for( int i = 0; i < L; i++ )
printf("%c", (char)( 'a' + rand() % 3 ) ); printf("\n");
for( int c = 0; c < N; c++ )
{
for( int i = 0; i < M; i++ )
printf("%c", (char)( 'a' + rand() % 3 ) ); printf("\n");
}
}
int main()
{
// gen();
freopen("abc2.in", "r", stdin);
freopen("abc2.out", "w", stdout);
start = clock();
int i, j, l, k;
gets( A );
L = strlen( A );
N = 0;
while( gets( cuv[++N] ) );
--N;
if( N == 0 )
{
printf("0\n");
return 0;
}
M = strlen(cuv[1]);
if( M > L )
{
printf("0\n");
return 0;
}
for( l = 0; l < L; l++ ) A[l] -= 'a' - 1;
for( i = 1; i <= N; i++ )
for( l = 0; l < M; l++ ) cuv[i][l] -= 'a' - 1;
clock_it( "reading" );
for( int i = 1; i <= N; i++ )
MyAC.add_word( string(cuv[i]) );
MyAC.build_automata();
// cout << MyAC.process_string() << endl;
int q;
for( i = 0; i < L; ++i )
{
while( g[ q ][ A[i] ] == -1 )
q = f[ q ];
q = g[ q ][ A[i] ];
// cout << "pos : " << i << " found " << v << endl;
ret += out[q];
}
cout << ret << endl;
clock_it( "total" );
return 0;
}