Recently has been in the optimization of the project string matching problem, so I think of the self-motive, before also read some articles, has not been implemented, now the project to use, and then saw some of the AC automata article, here to achieve a simple AC automata small interface, I am the realization of the automaton State structure using the trie tree, to achieve a simple, but to a certain extent caused by the increase in space complexity, welcome to error Correction and exchange of experience, the following is the code.
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define Char_extern 26/
The maximum number of next pointers for/trie, which should be set to 256 for all characters and then 0xFF & 6 7 typedef struct AC_NODE Ac_node;
8 typedef struct AC_NODE* ac_node_p; 9 #define QUEUE_TYPE ac_node_p//For this macro definition, the QUEUE can be encapsulated into an interface using one-#define FREE_QUEUE_VALUE//queue->value for dynamic request memory needs to do
This operation is int queue_node_num = 0;
14 15//define the queue structure used to calculate the invalid pointer. typedef struct QUEUE_NODE-queue_type value;
Queue_node *next of the struct;
}queue_node;
The typedef struct queue is {Queue_node *head;
Queue_node *tail;
}queue; */* Queue_node *queue_build_node (queue_type value) @ {Queue_node *node = (q
Ueue_node *) malloc (sizeof (Queue_node)); if (node = = NULL) PNs {#ifdef ac_debug ("Queue node Bulid error memory is full!!
\ n ");
#endif a return of NULL; 42}
Node->value = value;
Node->next = NULL;
The return node; * * * * * Queue initialization * Return-1 failed ELSE success * * * *queue_init queue ()
= (Queue *) malloc (sizeof (queue)); if (Ac_queue = = NULL) The {#ifdef ac_debug. printf ("Queue build failed memory is full\n
\ n ");
The #endif of the return NULL;
Ac_queue->head = Ac_queue->tail = Queue_build_node (NULL); if (Ac_queue->head = = NULL) {#ifdef ac_debug printf ("Queue Build head Error MEM
Ory is full\n\n ");
The #endif of the same, return NULL;
//ac_queue->head->next = ac_queue->tail;
Ac_queue return; * * * * * * * *queue for empty *return 1 is empty 0 is not empty * * * queue_is_empty int (queue *ac_queue) (Ac_queue->head = = Ac_queue->tail) retuRN 1;
The 0; 94} * * * * * * queue to the end of the team to add a node 98 * * * Queue_insert void (queue *ac_queue,queue_node *node) {101 Ac_que
Ue->tail->next = node;
102 Ac_queue->tail = node;
103 queue_node_num++;
104 #ifdef Ac_debug printf ("After insert the queue node num is%d: \ n", queue_node_num); 106 #endif 107} 108 109 */*queue Extract team first node value value 111 * * Queue_type Queue_first (queue *ac_queue) 113 {if (Queue_is_empty (Ac_queue)) Ac_debug 117 printf ("The queue is empty can not return head!!
\ n ");
118 #endif 119 return NULL; 121 122 Return ac_queue->head->next->value;
The team first does not have value, starting from the next node of the first team to take the value 123} 124//126 *queue Team first node out of the queue 127 * * * void Queue_delete (queue *ac_queue) 129 {130 131 if (Queue_is_empty (ac_queue)) 133 #ifdef ac_debug 134 printf ("The queue is empty we can not delet
e head\n\n ");
135 #endif 136 return; 137 } 138 139 Queue_node *head = ac_queue->head->next;
The team first does not have value, starting from the next node of the team first queue 141 Ac_queue->head->next = head->next; 142 143 if (head = = ac_queue->tail) 144 {//out queue for last element when queue is empty 145 Ac_queue->tail = Ac_queue->he
Ad 146} 147 148 free (head);
Release team first node memory 149 #ifdef AC_DEBUG 151 queue_node_num--;
printf ("After delete the queue node num is%d: \ n", queue_node_num); 153 #endif 154} 155 156/* 157 *queue Release Queue Memory 158 */159 void Queue_destroy (Queue *ac_queue) (161 Queue_nod)
e *p = NULL;
162 p = ac_queue->head; 163 164 while (P! = null) 165 {166 167 #ifdef Free_queue_value 168 if (p->value! = NULL) 169 Free (p->value);
Value for dynamic request for memory in case of this operation #endif 171 Queue_node *tmp = p->next;
172 173 if (P! = NULL) 174 free (p);
175 176 p = tmp; 177} 178} 179//ac State node 181 struct AC_NODe 182 {183 int final;//is the representation of the end of a pattern string 184 int model;//identifies which pattern string the pattern string is (if the suffix sub-pattern is considered, this should be changed to an integer linked list) 185 Ac_node *fail;
The failure pointer of the state node 186 187 struct Ac_node *next[char_extern];
188}; 189 190/* 191 * Create state node 192 */193 Ac_node *ac_node_build () 194 {195 int i; 196 Ac_node *node = (Ac_node *) MAL
LOC (sizeof (Ac_node)); 197 198 if (node = = NULL) 199 {#ifdef Ac_debug 201 printf ("Bulid node error the memory is full!!)
\ n ");
202 #endif 203 return NULL;
204} 205 206 node->final = 0;
207 Node->model =-1;
208 Node->fail = NULL; 209 (i = 0; i < Char_extern; i++) 211 {212 Node->next[i] = NULL; 213} 214 215 ret
URN node; 216} 217 218 219/* 220 * Create trie Tree 221 * return-1 failed Else success 222 */223 int ac_trie_build (Ac_node *root,char *str,in T Len,int model) 224 {225 int i; 226 ac_node *tmp = root; 227 228 if (tmp = = NULL) 229 {#ifdef A C_debug 231 printf ("Root has not been init!!!
\ n ");
232 #endif 233 return-1; 234} 235 236 for (i = 0; i < len; i++) 237 {238 239 */ac_node *next_node = tmp
->next[str[i]-' a ']; 241 This writes and then the Next_node operation causes the trie tree to fail, because Next_node has not been null 242 */243 244 int index = str[i]-' a '; If char_extern=256 index = str[i]&0xff 245 if (tmp->next[index] = = NULL) 246 {247 TM
P->next[index] = Ac_node_build (); 248 249 if (tmp->next[index] = = NULL) {251 #ifdef Ac_debug 252 printf ("Build node error in Ac_trie_build!!
\ n ");
253 #endif 254 return-1;
255} 257} 258 259 tmp = tmp->next[index];
260} 261 262 tmp->final = 1;
263 Tmp->model = model;
265 return 0; 266} 267 268 269/* 270 * Create invalid pointer function 271 */272 273 void Ac_build_fail (Ac_node *root,queue *ac_queue) 274 {275 if (root = null | | ac_queue = = NULL) 276 {277 #ifdef ac_debug 278 printf ("Build AC
Fail pointer error--input\n ");
279 #endif 280 return;
281} 282 283 int i;
284 Queue_node *q_node = NULL;
285 Ac_node *tmp_node = NULL;
286 Ac_node *fail_node = NULL;
287 288 Q_node = Queue_build_node (root);
289 Queue_insert (Ac_queue,q_node);
290 291 while (!queue_is_empty (ac_queue)) 292 {293 Tmp_node = Queue_first (ac_queue); 294 #ifdef Ac_debug
295 printf ("Out of the queue the AC node pointer is%p \ n", Tmp_node); 296 #endif 297 Queue_delete (ac_queue);//team first element out queue 298 299 for (i = 0; i < Char_extern; i++) 300 { The failure function of each character in the current state is computed by the queue using the BFS (breadth first) traversal Order 301 302 if (tmp_node->next[i]! = NULL)/if chart_extern=255 Tmpnod E->next[i&0xff] 303 {304 if (Tmp_node = = root) 305 {306 tmp_node->next[i]->fail = root; The failure pointer of the first layer node points to the root node 307} 308 Else 309