16 //#define MAXCHAR 1030
20 static int *MatchArray
;
32 static struct kword
**OutArray
;
34 static int *FailArray
;
38 static void AddStateTrans ( int, int ,int );
39 static void ComputeFail ( void );
40 static void Enter ( unsigned char * );
41 static void FindFail ( int state
, int s
, int a
);
42 static void QueueAdd ( int *queue
, int qbeg
, int new );
44 int RetrieveChar ( char **text
);
48 void MsrchInit ( struct kword
*klist
)
56 /* MaxState equals the number of characters */
57 for ( ktemp
= klist
; ktemp
!= NULL
; ktemp
= ktemp
->next
)
58 MaxState
+= strlen( ktemp
->word
);
60 MatchArray
= (int *) malloc ( sizeof(int) * MaxState
);
61 GotoArray
= (union GotoTable
*) malloc (sizeof (union GotoTable
) * MaxState
);
62 OutArray
= (struct kword
**) malloc (sizeof (struct kword
*) * MaxState
);
63 FailArray
= (int *) malloc (sizeof (int) * MaxState
);
65 for ( i
= 0; i
< MaxState
; i
++) {
66 MatchArray
[i
] = EMPTY_SLOT
;
71 AddStateTrans ( 0, 'a', FAIL_STATE
);
72 AddStateTrans ( 0, 'b', FAIL_STATE
);
74 for ( ; klist
!= NULL
; klist
= klist
->next
)
75 Enter ( klist
->word
);
77 for ( i
= 0; i
< MAXCHAR
; i
++)
78 if ( GotoArray
[0].BranchTable
[i
] == FAIL_STATE
)
79 GotoArray
[0].BranchTable
[i
] = 0;
84 /* Add transition from OldState to NewState for MatchChar */
85 static void AddStateTrans ( int OldState
, int MatchChar
, int NewState
)
89 if ( MatchArray
[OldState
] == EMPTY_SLOT
) {
90 MatchArray
[OldState
] = MatchChar
;
91 GotoArray
[OldState
].GotoState
= NewState
;
95 if ( MatchArray
[OldState
] == MULTI_WAY
)
96 GotoArray
[OldState
].BranchTable
[MatchChar
] = NewState
;
100 temp
= (int *) malloc ( sizeof(int) * MAXCHAR
);
102 for ( i
= 0; i
< MAXCHAR
; i
++ )
103 temp
[i
] = FAIL_STATE
;
106 temp
[MatchArray
[OldState
]] = GotoArray
[OldState
].GotoState
;
108 temp
[MatchChar
] = NewState
;
110 MatchArray
[OldState
] = MULTI_WAY
;
111 GotoArray
[OldState
].BranchTable
= temp
;
115 /* Add word to the list of words the program recognises */
116 static void Enter ( unsigned char *kword
)
127 for ( ; *kword
!= '\0'; kword
++ ) {
128 if ( MatchArray
[state
] == *kword
)
129 state
= GotoArray
[state
].GotoState
;
132 if ( MatchArray
[state
] == MULTI_WAY
) {
133 if (( k
= GotoArray
[state
].BranchTable
[*kword
] ) == FAIL_STATE
)
142 for ( ; *kword
!= '\0'; kword
++ ) {
145 if ( HighState
>= MaxState
) {
146 printf("Too many states!\n");
150 AddStateTrans ( state
, *kword
, HighState
);
154 ktemp
= (struct kword
*) malloc ( sizeof ( struct kword
));
156 ktemp
->next
= OutArray
[state
];
157 OutArray
[state
] = ktemp
;
160 static void ComputeFail()
162 int *queue
, qbeg
, r
, s
;
165 /* Allocate a queue */
166 queue
= (int *) malloc ( sizeof( int ) * MaxState
);
170 for ( i
= 0; i
< MAXCHAR
; i
++ )
171 if (( s
= GotoArray
[0].BranchTable
[i
] ) != 0 ) {
173 QueueAdd ( queue
, qbeg
, s
);
176 while ( queue
[qbeg
] != 0)
181 if ( MatchArray
[r
] == EMPTY_SLOT
)
185 if ( MatchArray
[r
] == MULTI_WAY
) {
186 for ( i
= 0; i
< MAXCHAR
; i
++ )
187 if (( s
= GotoArray
[r
].BranchTable
[i
] ) != FAIL_STATE
) {
188 QueueAdd ( queue
, qbeg
, s
);
189 FindFail ( FailArray
[r
], s
, i
);
193 QueueAdd ( queue
, qbeg
, GotoArray
[r
].GotoState
);
194 FindFail ( FailArray
[r
], GotoArray
[r
].GotoState
, MatchArray
[r
] );
201 static void FindFail ( int s1
, int s2
, int a
)
204 struct kword
*ktemp
, kdummy
, *out_copy
, *kscan
;
206 for ( ; ; s1
= FailArray
[s1
] )
207 if ( MatchArray
[s1
] == a
) {
208 if (( on_fail
= GotoArray
[s1
].GotoState
) != FAIL_STATE
)
212 if ( MatchArray
[s1
] == MULTI_WAY
)
213 if (( on_fail
= GotoArray
[s1
].BranchTable
[a
] ) != FAIL_STATE
)
216 FailArray
[s2
] = on_fail
;
218 if( OutArray
[on_fail
] == NULL
)
222 kscan
= OutArray
[on_fail
];
223 out_copy
= malloc ( sizeof (struct kword
));
224 out_copy
->word
= kscan
->word
;
225 out_copy
->next
= NULL
;
227 for ( kscan
= kscan
->next
; kscan
!= NULL
; kscan
= kscan
->next
) {
229 ktemp
= malloc ( sizeof ( struct kword
));
230 ktemp
->word
= kscan
->word
;
231 ktemp
->next
= out_copy
->next
;
232 out_copy
->next
= ktemp
;
236 if (( kdummy
.next
= OutArray
[s2
] ) != NULL
) {
238 for ( ; ktemp
->next
->next
!= NULL
; ktemp
= ktemp
->next
)
240 ktemp
->next
->next
= out_copy
;
244 OutArray
[s2
] = out_copy
;
247 static void QueueAdd ( int *queue
, int qbeg
, int new )
256 for ( ; queue
[q
] != 0; q
= queue
[q
] )
264 /* Do the actual search */
265 int MsrchGo ( char **text
)
272 while (( c
= RetrieveChar( text
) ) != EOF
) {
276 if ( state
== 0 || ( mm
= MatchArray
[state
] ) == MULTI_WAY
)
277 g
= GotoArray
[state
].BranchTable
[c
];
281 g
= GotoArray
[state
].GotoState
;
286 if ( g
!= FAIL_STATE
)
289 state
= FailArray
[state
];
294 if (( kscan
= OutArray
[state
] ) != NULL
)
295 for ( ; kscan
!= NULL
; kscan
= kscan
->next
)
296 /* Break on the first result */
297 return (textcolumn
- strlen(kscan
->word
));
302 void MsrchEnd ( void )
308 for ( i
= 0; i
< MaxState
; i
++ )
309 if ( MatchArray
[i
] == MULTI_WAY
)
310 free ( GotoArray
[i
].BranchTable
);
316 for ( i
= 0; i
< MaxState
; i
++ )
317 if ( OutArray
[i
] != NULL
)
318 for ( kscan
= OutArray
[i
]; kscan
!= NULL
; kscan
= kscan
->next
)
337 int aho( char **text
, char **pattern
, int m
, int n
, int trow
, int tcolumn
, int prow
, int tlength
)
340 textlength
= tlength
;
341 textcolumn
= tcolumn
;
343 struct kword
*khead
, *ktemp
;
354 pattern_small
= malloc (m
+ 1);
356 for( i
= 0; i
< m
; i
++)
357 pattern_small
[i
] = pattern
[prow
][i
];
359 ktemp
= ( struct kword
* ) malloc ( sizeof ( struct kword
));
360 ktemp
->word
= pattern_small
;
363 if (khead
!= 0 && khead
!= ktemp
)
364 if (khead
->word
== ktemp
->word
)
365 printf("Words point to the same thing - this is not valid\n");
369 /* Setup system and pass list of words */
373 int result
= MsrchGo( text
);
378 free ( pattern_small
);
383 int RetrieveChar( char **text
)
385 if ( textcolumn
< textlength
) {
387 return text
[textrow
][textcolumn
- 1];