Pagini recente » Cod sursa (job #2791668) | Cod sursa (job #1007566) | Cod sursa (job #2037379) | Cod sursa (job #2944084) | Cod sursa (job #1572488)
#include <cstdio>
#include <algorithm>
#include <deque>
#include <vector>
#include <cstring>
const int SIGMA = 3;
using namespace std;
int NrWords, Answer, Vector[1 << 16];
char String[1 << 24], Word[1 << 16][1 << 6], NewWord[1 << 16][1 << 6];
class state_machine {
private:
struct tree {
int cnt_words;
int cnt_children;
int cnt_occurrences;
tree *children[SIGMA];
tree *back_node;
vector <tree *> front_node;
tree () {
cnt_words = NULL;
back_node = NULL;
cnt_children = NULL;
cnt_occurrences = NULL;
for( int i = 0; i < SIGMA; i ++ )
children[i] = NULL;
front_node.clear();
}
} *Root = new tree;
void insert_word( tree *Node, char *String ) {
if( *String == NULL ) {
Node -> cnt_words ++;
return;
}
if( Node -> children[*String - 'a'] == NULL ) {
Node -> children[*String - 'a'] = new tree;
Node -> cnt_children ++;
}
insert_word( Node -> children[*String - 'a'], String + 1 );
return;
}
void build_back_edges( tree *start_node ) {
deque <tree *> Queue;
Queue.push_back(start_node);
while( !Queue.empty() ) {
tree *Node = Queue.front();
for( int i = 0; i < SIGMA; i ++ ) {
if( Node -> children[i] != NULL ) {
tree *Aux = Node -> back_node;
while( Aux && Aux -> children[i] == NULL )
Aux = Aux -> back_node;
if( Aux == NULL )
Node -> children[i] -> back_node = Root;
else
Node -> children[i] -> back_node = Aux -> children[i];
Node -> children[i] -> back_node -> front_node.push_back(Node -> children[i]);
Queue.push_back( Node -> children[i] );
}
}
Queue.pop_front();
}
return;
}
void build_occurrences( tree *Node, char *String ) {
if( *String == NULL )
return;
while( Node != Root && Node -> children[*String - 'a'] == NULL )
Node = Node -> back_node;
if( Node -> children[*String - 'a'] != NULL )
Node = Node -> children[*String - 'a'];
Node -> cnt_occurrences ++;
build_occurrences( Node, String + 1 );
return;
}
void build_partial_sum( tree *Node ) {
for( int i = 0; i < Node -> front_node.size(); i ++ ) {
build_partial_sum( Node -> front_node[i] );
Node -> cnt_occurrences += Node -> front_node[i] -> cnt_occurrences;
}
return;
}
int count_occurrences( tree *Node, char *String ) {
if( *String == NULL )
return Node -> cnt_occurrences;
if( Node -> children[*String - 'a'] != NULL )
return count_occurrences( Node -> children[*String - 'a'], String + 1 );
return 0;
}
public:
void insert_word( char *String ) {
insert_word( Root, String );
return;
}
void build_occurrences( char *String ) {
build_back_edges( Root );
build_occurrences( Root, String );
build_partial_sum( Root );
return;
}
int count_occurrences( char *String ) {
return count_occurrences( Root, String );
}
} my_state_machine;
inline int CMP( int a, int b ) {
for( int i = 0; Word[a][i] != 0; i ++ )
if( Word[a][i] != Word[b][i] )
return Word[a][i] < Word[b][i];
return a < b;
}
inline int CMP2( int a, int b ) {
for( int i = 0; NewWord[a][i] != 0; i ++ )
if( NewWord[a][i] != NewWord[b][i] )
return 0;
return 1;
}
int main () {
freopen( "abc2.in" , "r", stdin );
freopen( "abc2.out", "w", stdout );
fgets( String, 1 << 24, stdin ); String[strlen( String ) - 1] = 0;
while( fgets( Word[++NrWords], 1 << 6, stdin ) ) {
Word[NrWords][strlen( Word[NrWords] ) - 1] = 0;
my_state_machine.insert_word( Word[NrWords] );
Vector[NrWords] = NrWords;
}
my_state_machine.build_occurrences( String );
sort( Vector + 1, Vector + NrWords + 1, CMP );
for( int i = 1; i <= NrWords; i ++ )
memcpy( NewWord[i], Word[Vector[i]], sizeof( Word[Vector[i]] ));
for( int i = 1; i <= NrWords; i ++ ) {
while( CMP2( i, i + 1 ) )
i ++;
Answer += my_state_machine.count_occurrences( NewWord[i] );
}
printf( "%d\n", Answer );
return 0;
}