/*
An AC automatic machine template question has timed out more than 20 times. After being modified for half a day, the code marks a key step for modifying the process from TLE to AC, it looks like the details of array passed as function parameters, but I still don't understand it. If the great God understands the reason, I hope you can give me some advice !!!
The problem was finally solved. It turned out that the repeated call of strlen () function in the loop resulted in TLE. Thank you for your help!
Note: to traverse a character array 'str', write down the value of 'strlen (str) 'with a variable to avoid calling strlen () continuously in a loop ()
*/
Give some words first, then give an article, and count the number of words in the article. Each word here is counted only once.
[Cpp]
# Include "iostream"
# Include "string"
# Include "queue"
Using namespace std;
Char s [2, 1000001], p [55];
// Node Structure
Struct Node
{
Int cnt;
Node * fail;
Node * next [26];
};
Node * root = new Node;
// Initialize the node
Void init (Node * t)
{
Memset (t-> next, NULL, sizeof (t-> next ));
T-> cnt = 0;
T-> fail = NULL;
}
// Insert a new word
Void insert (char * str)
{
Int I = 0, k;
Node * p = root;
Node * newnode;
While (str [I]) {// if you use for (I = 0; I <strlen (str); I ++), you must first write down the value of strlen (str, prevent TLE
K = str [I]-'A ';
If (p-> next [k] = NULL ){
Newnode = new Node;
Init (newnode );
P-> next [k] = newnode;
P = newnode;
}
Else {
P = p-> next [k];
}
I ++;
}
P-> cnt ++;
}
// Determine the fail pointer
Void makeFail ()
{
Node * front;
Queue <Node *> q;
Q. push (root );
While (! Q. empty ()){
Front = q. front ();
Q. pop ();
For (int I = 0; I <26; I ++ ){
If (front-> next [I]! = NULL) {// if the parent node has child I, find the fail pointer of child I.
If (front = root)
Front-> next [I]-> fail = root; // The fail pointer of the node connected to the root node points to the root node
Else {
Node * temp = front;
While (temp-> fail! = NULL) {// The parent node fail pointer is not NULL
If (temp-> fail-> next [I]! = NULL) {// The parent node fail Pointer Points to the node with child I
Front-> next [I]-> fail = temp-> fail-> next [I];
Break;
}
Temp = temp-> fail; // The parent node is transferred up.
}
If (temp-> fail = NULL)
Front-> next [I]-> fail = root;
}
Q. push (front-> next [I]); // locate the fail pointer of the child I and add the child I to the queue
}
}
}
}
// Search for words in the article
Int search (char * str)
{
Node * p = root;
Node * temp = NULL;
Int I = 0, k, ans = 0;
While (str [I]) {
K = str [I]-'A ';
While (p! = Root & p-> next [k] = NULL ){
P = p-> fail;
}
If (p-> next [k]! = NULL) {// p records the longest suffix matching at the current position, and continues matching from this branch next time
P = p-> next [k];
Temp = p; // use temp to continue searching for a suffix with a shorter Current Position
While (temp! = Root & temp-> cnt! =-1 ){
Ans + = temp-> cnt; // note that it must be + =, instead of ++, because cnt may be 0
Temp-> cnt =-1;
Temp = temp-> fail;
}
}
I ++;
}
Return ans;
}
// Release the memory
Void freedom (Node * p)
{
For (int I = 0; I <26; I ++ ){
If (p-> next [I]! = NULL)
Freedom (p-> next [I]);
}
Delete p;
}
Int main ()
{
Int t, k, I, ans;
Scanf ("% d", & t );
While (t --){
Init (root );
Scanf ("% d", & k );
Getchar ();
While (k --){
Gets (p );
Insert (p );
}
MakeFail ();
Gets (s );
Ans = search (s );
Printf ("% d \ n", ans );
For (I = 0; I <26; I ++) {// note that the root cannot be deleted.
If (root-> next [I]! = NULL)
Freedom (root-> next [I]);
}
}
Delete root;
Return 0;
}
# Include "iostream"
# Include "string"
# Include "queue"
Using namespace std;
Char s [2, 1000001], p [55];
// Node Structure
Struct Node
{
Int cnt;
Node * fail;
Node * next [26];
};
Node * root = new Node;
// Initialize the node
Void init (Node * t)
{
Memset (t-> next, NULL, sizeof (t-> next ));
T-> cnt = 0;
T-> fail = NULL;
}
// Insert a new word
Void insert (char * str)
{
Int I = 0, k;
Node * p = root;
Node * newnode;
While (str [I]) {// if you use for (I = 0; I <strlen (str); I ++), you must first write down the value of strlen (str, prevent TLE
K = str [I]-'A ';
If (p-> next [k] = NULL ){
Newnode = new Node;
Init (newnode );
P-> next [k] = newnode;
P = newnode;
}
Else {
P = p-> next [k];
}
I ++;
}
P-> cnt ++;
}
// Determine the fail pointer
Void makeFail ()
{
Node * front;
Queue <Node *> q;
Q. push (root );
While (! Q. empty ()){
Front = q. front ();
Q. pop ();
For (int I = 0; I <26; I ++ ){
If (front-> next [I]! = NULL) {// if the parent node has child I, find the fail pointer of child I.
If (front = root)
Front-> next [I]-> fail = root; // The fail pointer of the node connected to the root node points to the root node
Else {
Node * temp = front;
While (temp-> fail! = NULL) {// The parent node fail pointer is not NULL
If (temp-> fail-> next [I]! = NULL) {// The parent node fail Pointer Points to the node with child I
Front-> next [I]-> fail = temp-> fail-> next [I];
Break;
}
Temp = temp-> fail; // The parent node is transferred up.
}
If (temp-> fail = NULL)
Front-> next [I]-> fail = root;
}
Q. push (front-> next [I]); // locate the fail pointer of the child I and add the child I to the queue
}
}
}
}
// Search for words in the article
Int search (char * str)
{
Node * p = root;
Node * temp = NULL;
Int I = 0, k, ans = 0;
While (str [I]) {
K = str [I]-'A ';
While (p! = Root & p-> next [k] = NULL ){
P = p-> fail;
}
If (p-> next [k]! = NULL) {// p records the longest suffix matching at the current position, and continues matching from this branch next time
P = p-> next [k];
Temp = p; // use temp to continue searching for a suffix with a shorter Current Position
While (temp! = Root & temp-> cnt! =-1 ){
Ans + = temp-> cnt; // note that it must be + =, instead of ++, because cnt may be 0
Temp-> cnt =-1;
Temp = temp-> fail;
}
}
I ++;
}
Return ans;
}
// Release the memory
Void freedom (Node * p)
{
For (int I = 0; I <26; I ++ ){
If (p-> next [I]! = NULL)
Freedom (p-> next [I]);
}
Delete p;
}
Int main ()
{
Int t, k, I, ans;
Scanf ("% d", & t );
While (t --){
Init (root );
Scanf ("% d", & k );
Getchar ();
While (k --){
Gets (p );
Insert (p );
}
MakeFail ();
Gets (s );
Ans = search (s );
Printf ("% d \ n", ans );
For (I = 0; I <26; I ++) {// note that the root cannot be deleted.
If (root-> next [I]! = NULL)
Freedom (root-> next [I]);
}
}
Delete root;
Return 0;
}