You are on page 1of 10

Harshit Kushwah

IIT2020039
1.

Knuth-Morris and Pratt introduce a linear time algorithm for the string matching problem.
A matching time of O (n) is achieved by avoiding comparison with an element of 'S' that
have previously been involved in comparison with some element of the pattern 'p' to be
matched. i.e., backtracking on the string 'S' never occurs

Components of KMP Algorithm:

Pseudo Code for KMP Algorithm


table[0] = 0
i = 0, j = 1
while (j < n) { // n is the length of pattern p
if (p[i] == p[j])
{ table[j] = i
+ 1; i++;
j++;
} else
{
if (i != 0) {
i = table[i - 1];
// Do not increment j here
} else {
table[j] =
0; j++;
}

Time Complexity: O(m + n)

Space Complexity: O(m + n)

2.
// C++ program for implementation of KMP pattern searching
// algorithm
#include <bits/stdc++.h>

void computeLPSArray(char* pat, int M, int* lps);

// Prints occurrences of txt[] in pat[]


void KMPSearch(char* pat, char* txt)
{
int M = strlen(pat);
int N = strlen(txt);

// create lps[] that will hold the longest prefix suffix


// values for pattern
int lps[M];

// Preprocess the pattern (calculate lps[] array)


computeLPSArray(pat, M, lps);

int i = 0; // index for txt[]


int j = 0; // index for pat[]
while (i < N) {
if (pat[j] == txt[i]) {
j++;
i++;
}

if (j == M) {
printf("Found pattern at index %d ", i - j);
j = lps[j - 1];
}

// mismatch after j matches


else if (i < N && pat[j] != txt[i]) {
// Do not match lps[0..lps[j-1]] characters,
// they will match
anyway if (j != 0)
j = lps[j - 1];
else
i = i + 1;
}
}
}

// Fills lps[] for given patttern pat[0..M-1]


void computeLPSArray(char* pat, int M, int* lps)
{
// length of the previous longest prefix suffix
int len = 0;

lps[0] = 0; // lps[0] is always 0

// the loop calculates lps[i] for i = 1 to M -1


int i = 1;
while (i < M) {
if (pat[i] == pat[len])
{ len++;
lps[i] = len;
i++;
}
else // (pat[i] != pat[len])
{
// This is tricky. Consider the example.
// AAACAAAA and i = 7. The idea is similar
// to search
step. if (len !=
0) {
len = lps[len - 1];

// Also, note that we do not increment


// i here
}
else // if (len == 0)
{
lps[i] =
0; i++;
}
}
}
}

// Driver program to test above


function int main()
{
char S= ”ABBAAABBCABCABBABBA”;
char pat[] =
"ABBA";
KMPSearch(pat, S);
return 0;
3.
A Trie is an advanced data structure that is sometimes also known as prefix tree or
digital tree. It is a tree that stores the data in an ordered and efficient way. We
generally use trie's to store strings. Each node of a trie can have as many as 26
references (pointers).

Insert of a node in the Trie

The first operation is to insert a new node into the trie. Before we start the
implementation, it is important to understand some points:
Every letter of the input key (word) is inserted as an individual in the Trie_node. Note
that children point to the next level of Trie nodes.

The key character array acts as an index of children.

If the present node already has a reference to the present letter, set the present node
to that referenced node. Otherwise, create a new node, set the letter to be equal to the
present letter, and even start the present node with this new node.

public class Data_Trie {


private Node_Trie
root; public
Data_Trie(){
this.root = new Node_Trie();
}
public void insert(String
word){ Node_Trie current =
root; int length =
word.length();
for (int x = 0; x < length; x+
+){ char L =
word.charAt(x);
Node_Trie node =
current.getNode().get(L); if (node ==
null){
node = new Node_Trie ();
current.getNode().put(L,
node);
}
current = node;

Searching a node in Trie

The second operation is to search for a node in a Trie. The searching operation is similar to
the insertion operation. The search operation is used to search a key in the trie. The
implementation of the searching operation is shown below.

class Search_Trie {

private Node_Trie Prefix_Search(String W)


{ Node_Trie node = R;
for (int x = 0; x < W.length(); x++)
{ char curLetter = W.charAt(x);
if (node.containsKey(curLetter))
{
node = node.get(curLetter);
}
else {
return null;
}
}
return node;
}

public boolean search(String W) {


Node_Trie node = Prefix_Search(W);
return node != null &&
node.isEnd();
}

4.

In Trie structure, we have a field to store end of word marker, we call it isLeaf in below
implementation. To count words, we need to simply traverse the Trie and count all nodes
where isLeaf is set.

// C++ implementation to count words in a


trie #include <bits/stdc++.h>
using namespace std;

#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])

// Alphabet size (# of
symbols) #define
ALPHABET_SIZE (26)

// Converts key current character into index


// use only 'a' through 'z' and lower case
#define CHAR_TO_INDEX(c) ((int)c - (int)'a')

// Trie node
struct
TrieNode
{
struct TrieNode *children[ALPHABET_SIZE];

// isLeaf is true if the node represents


// end of a
word bool
isLeaf;
};

// Returns new trie node (initialized to


NULLs) struct TrieNode *getNode(void)
for (int i = 0; i < ALPHABET_SIZE; i+
+) pNode->children[i] = NULL;

return pNode;
}

// If not present, inserts key into trie


// If the key is prefix of trie node, just
// marks leaf node
void insert(struct TrieNode *root, const char *key)
{
int length = strlen(key);

struct TrieNode *pCrawl = root;

for (int level = 0; level < length; level++)


{
int index = CHAR_TO_INDEX(key[level]);
if (!pCrawl->children[index])
pCrawl->children[index] = getNode();

pCrawl = pCrawl->children[index];
}

// mark last node as


leaf pCrawl->isLeaf =
true;
}

// Function to count number of words


int wordCount(struct TrieNode *root)
{
int result = 0;

// Leaf denotes end of a word


if (root -> isLeaf)
result++;

for (int i = 0; i < ALPHABET_SIZE; i++)


if (root -> children[i])
result += wordCount(root -> children[i]);

return result;
}

// Driver
int main()
{
// Input keys (use only 'a' through 'z'
// and lower case)
char keys[][8] = {"the", "a", "there", "answer",
"any", "by", "bye", "their"};

struct TrieNode *root = getNode();

// Construct Trie
for (int i = 0; i < ARRAY_SIZE(keys); i+
+) insert(root, keys[i]);

cout <<

wordCount(root);

return 0;
}

5.

// C++ program to sort an array of strings


// using Trie
#include <bits/stdc+
+.h> using namespace
std;

const int MAX_CHAR =

26; struct Trie {

// index is set when node is a leaf


// node, otherwise -
1; int index;

Trie* child[MAX_CHAR];

/*to make new


trie*/ Trie()
{
for (int i = 0; i < MAX_CHAR; i+
+) child[i] = NULL;
index = -1;
}
};
void insert(Trie* root, string str, int index)
{
Trie* node = root;

for (int i = 0; i < str.size(); i++) {

/* taking ascii value to find index of


child node */
char ind = str[i] - 'a';

/* making new path if not already */


if (!node->child[ind])
node->child[ind] = new Trie();

// go to next node
node = node->child[ind];
}

// Mark leaf (end of word) and store


// index of word in
arr[] node->index =
index;
}

/* function for preorder traversal */


bool preorder(Trie* node, string arr[])
{
if (node == NULL)
return false;

for (int i = 0; i < MAX_CHAR; i++) {


if (node->child[i] != NULL) {

/* if leaf node then print key*/


if (node->child[i]->index != -1)
cout << arr[node->child[i]->index] << endl;

preorder(node->child[i], arr);
}
}
}

void printSorted(string arr[], int n)


{
Trie* root = new Trie();

// insert all keys of dictionary into trie


for (int i = 0; i < n; i++)
6JBGBJ6

insert(root, arr[i], i);

// print keys in lexicographic order preorder(root, arr);


}

// Driver code int main()


{
string arr[] = { "abc", "xy", "bcd" }; int n = sizeof(arr) / sizeof(arr[0]); printSorted
return 0;
}
6.

You might also like