Pattern Searching | Set 6 (Efficient Construction of Finite Automata)
In the previous post, we discussed the Finite Automata-based pattern searching algorithm. The FA (Finite Automata) construction method discussed in the previous post takes O((m^3)*NO_OF_CHARS) time. FA can be constructed in O(m*NO_OF_CHARS) time. In this post, we will discuss the O(m*NO_OF_CHARS) algorithm for FA construction. The idea is similar to LPs (longest prefix suffix) array construction discussed in the KMP algorithm. We use previously filled rows to fill a new row.
The above diagrams represent graphical and tabular representations of pattern ACACAGA.
Algorithm:
1) Fill the first row. All entries in the first row are always 0 except the entry for the pat[0] character. For pat[0] character, we always need to go to state 1.
2) Initialize lps as 0. lps for the first index is always 0.
3) Do following for rows at index i = 1 to M. (M is the length of the pattern)
…..a) Copy the entries from the row at index equal to lps.
…..b) Update the entry for pat[i] character to i+1.
…..c) Update lps “lps = TF[lps][pat[i]]” where TF is the 2D array which is being constructed.
Following is the implementation for the above algorithm.
Implementation
C++
#include <bits/stdc++.h>
using namespace std;
#define NO_OF_CHARS 256
void computeTransFun( char * pat, int M, int TF[][NO_OF_CHARS])
{
int i, lps = 0, x;
for (x = 0; x < NO_OF_CHARS; x++)
TF[0][x] = 0;
TF[0][pat[0]] = 1;
for (i = 1; i <= M; i++) {
for (x = 0; x < NO_OF_CHARS; x++)
TF[i][x] = TF[lps][x];
TF[i][pat[i]] = i + 1;
if (i < M)
lps = TF[lps][pat[i]];
}
}
void search( char pat[], char txt[])
{
int M = strlen (pat);
int N = strlen (txt);
int TF[M + 1][NO_OF_CHARS];
computeTransFun(pat, M, TF);
int i, j = 0;
for (i = 0; i < N; i++) {
j = TF[j][txt[i]];
if (j == M) {
cout << "pattern found at index " << i - M + 1 << endl;
}
}
}
int main()
{
char txt[] = "ACACACACAGAAGA ACACAGAACACAGA GEEKS" ;
char pat[] = "ACACAGA" ;
search(pat, txt);
return 0;
}
|
C
#include <stdio.h>
#include <string.h>
#define NO_OF_CHARS 256
void computeTransFun( char * pat, int M, int TF[][NO_OF_CHARS])
{
int i, lps = 0, x;
for (x = 0; x < NO_OF_CHARS; x++)
TF[0][x] = 0;
TF[0][pat[0]] = 1;
for (i = 1; i <= M; i++) {
for (x = 0; x < NO_OF_CHARS; x++)
TF[i][x] = TF[lps][x];
TF[i][pat[i]] = i + 1;
if (i < M)
lps = TF[lps][pat[i]];
}
}
void search( char * pat, char * txt)
{
int M = strlen (pat);
int N = strlen (txt);
int TF[M + 1][NO_OF_CHARS];
computeTransFun(pat, M, TF);
int i, j = 0;
for (i = 0; i < N; i++) {
j = TF[j][txt[i]];
if (j == M) {
printf ( "\n pattern found at index %d" , i - M + 1);
}
}
}
int main()
{
char * txt = "GEEKS FOR GEEKS" ;
char * pat = "GEEKS" ;
search(pat, txt);
getchar ();
return 0;
}
|
Java
class GFG
{
static int NO_OF_CHARS = 256 ;
static void computeTransFun( char [] pat,
int M, int TF[][])
{
int i, lps = 0 , x;
for (x = 0 ; x < NO_OF_CHARS; x++)
{
TF[ 0 ][x] = 0 ;
}
TF[ 0 ][pat[ 0 ]] = 1 ;
for (i = 1 ; i < M; i++)
{
for (x = 0 ; x < NO_OF_CHARS; x++)
{
TF[i][x] = TF[lps][x];
}
TF[i][pat[i]] = i + 1 ;
if (i < M)
{
lps = TF[lps][pat[i]];
}
}
}
static void search( char pat[], char txt[])
{
int M = pat.length;
int N = txt.length;
int [][] TF = new int [M + 1 ][NO_OF_CHARS];
computeTransFun(pat, M, TF);
int i, j = 0 ;
for (i = 0 ; i < N; i++)
{
j = TF[j][txt[i]];
if (j == M)
{
System.out.println( "pattern found at index " +
(i - M + 1 ));
}
}
}
public static void main(String[] args)
{
char txt[] = "GEEKS FOR GEEKS" .toCharArray();
char pat[] = "GEEKS" .toCharArray();
search(pat, txt);
}
}
|
Python3
NO_OF_CHARS = 256
def computeTransFun(pat, M, TF):
lps = 0
for x in range (NO_OF_CHARS):
TF[ 0 ][x] = 0
TF[ 0 ][ ord (pat[ 0 ])] = 1
for i in range ( 1 , M + 1 ):
for x in range (NO_OF_CHARS):
TF[i][x] = TF[lps][x]
if (i < M):
TF[i][ ord (pat[i])] = i + 1
lps = TF[lps][ ord (pat[i])]
def search(pat, txt):
M = len (pat)
N = len (txt)
TF = [[ 0 for i in range (NO_OF_CHARS)] for j in range (M + 1 )]
computeTransFun(pat, M, TF)
j = 0
for i in range (N):
j = TF[j][ ord (txt[i])]
if (j = = M):
print ( "pattern found at index" , i - M + 1 )
txt = "ACACACACAGAAGA ACACAGAACACAGA GEEKS"
pat = "ACACAGA"
search(pat, txt)
|
C#
using System;
class GFG
{
static int NO_OF_CHARS = 256;
static void computeTransFun( char [] pat,
int M, int [,]TF)
{
int i, lps = 0, x;
for (x = 0; x < NO_OF_CHARS; x++)
{
TF[0,x] = 0;
}
TF[0,pat[0]] = 1;
for (i = 1; i < M; i++)
{
for (x = 0; x < NO_OF_CHARS; x++)
{
TF[i,x] = TF[lps,x];
}
TF[i,pat[i]] = i + 1;
if (i < M)
{
lps = TF[lps,pat[i]];
}
}
}
static void search( char []pat, char []txt)
{
int M = pat.Length;
int N = txt.Length;
int [,] TF = new int [M + 1,NO_OF_CHARS];
computeTransFun(pat, M, TF);
int i, j = 0;
for (i = 0; i < N; i++)
{
j = TF[j,txt[i]];
if (j == M)
{
Console.WriteLine( "pattern found at index " +
(i - M + 1));
}
}
}
public static void Main(String[] args)
{
char []txt = "GEEKS FOR GEEKS" .ToCharArray();
char []pat = "GEEKS" .ToCharArray();
search(pat, txt);
}
}
|
Javascript
<script>
let NO_OF_CHARS = 256;
function computeTransFun(pat,M,TF)
{
let i, lps = 0, x;
for (x = 0; x < NO_OF_CHARS; x++)
{
TF[0][x] = 0;
}
TF[0][pat[0].charCodeAt(0)] = 1;
for (i = 1; i < M; i++)
{
for (x = 0; x < NO_OF_CHARS; x++)
{
TF[i][x] = TF[lps][x];
}
TF[i][pat[i].charCodeAt(0)] = i + 1;
if (i < M)
{
lps = TF[lps][pat[i].charCodeAt(0)];
}
}
}
function search(pat,txt)
{
let M = pat.length;
let N = txt.length;
let TF = new Array(M + 1);
for (let i=0;i<M+1;i++)
{
TF[i]= new Array(NO_OF_CHARS);
for (let j=0;j<NO_OF_CHARS;j++)
{
TF[i][j]=0;
}
}
computeTransFun(pat, M, TF);
let i, j = 0;
for (i = 0; i < N; i++)
{
j = TF[j][txt[i].charCodeAt(0)];
if (j == M)
{
document.write( "pattern found at index " +
(i - M + 1)+ "<br>" );
}
}
}
let txt = "GEEKS FOR GEEKS" .split( "" );
let pat = "GEEKS" .split( "" );
search(pat, txt);
</script>
|
Output:
pattern found at index 0
pattern found at index 10
Time Complexity for FA construction is O(M*NO_OF_CHARS). The code for search is the same as the previous post and the time complexity for it is O(n).
Last Updated :
09 Sep, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...