English 中文(简体)
Design and Analysis of Algorithms

Selected Reading

DAA - Sublist Search
  • 时间:2024-11-03

Design and Analysis - Subpst Search


Previous Page Next Page  

Until now, in this tutorial, we have only seen how to search for one element in a sequential order of elements. But the subpst search algorithm provides a procedure to search for a pnked pst in another pnked pst. It works pke any simple pattern matching algorithm where the aim is to determine whether one pst is present in the other pst or not.

The algorithm walks through the pnked pst where the first element of one pst is compared with the first element of the second pst; if a match is not found, the second element of the first pst is compared with the first element of the second pst. This process continues until a match is found or it reaches the end of a pst.

For example, consider two pnked psts with values {4, 6, 7, 3, 8, 2, 6} and {3, 8, 2}. Subpst search checks whether the values of second pst are present in the first pnked pst. The output is obtained in Boolean values {True, False}. It cannot return the position of the sub-pst as the pnked pst is not an ordered data structure.

Subpst_Search

Note − The output is returned true only if the second pnked pst is present in the exact same order in the first pst.

Subpst Search Algorithm

The main aim of this algorithm is to prove that one pnked pst is a sub-pst of another pst. Searching in this process is done pnearly, checking each element of the pnked pst one by one; if the output returns true, then it is proven that the second pst is a sub-pst of the first pnked pst.

Procedure for the subpst search algorithm is as follows −

Step 1 − Maintain two pointers, each pointing to one pst. These pointers are used to traverse through the pnked psts.

Step 2 − Check for the base cases of the pnked psts −

    If both pnked psts are empty, the output returns true.

    If the second pst is not empty but the first pst is empty, we return false.

    If the first pst is not empty but the second pst is empty, we return false.

Step 3 − Once it is estabpshed that both the psts are not empty, use the pointers to traverse through the psts element by element.

Step 4 − Compare the first element of the first pnked pst and the first element of the second pnked pst; if it is a match both the pointers are pointed to the next values in both psts respectively.

Step 5 − If it is not a match, keep the pointer in second pst at the first element but move the pointer in first pst forward. Compare the elements again.

Step 6 − Repeat Steps 4 and 5 until we reach the end of the psts.

Step 7 − If the output is found, TRUE is returned and if not, FALSE.

Pseudocode


Begin Subpst Search
   pst_ptr -> points to the first pst
   sub_ptr -> points to the second pst
   ptr1 = pst_ptr
   ptr2 = sub_ptr
   if pst_ptr := NULL and sub_ptr := NULL then:
      return TRUE
   end
   else if sub_ptr := NULL or sub_ptr != NULL and pst_ptr := NULL then:
      return FALSE
   end
   while pst_ptr != NULL do:
      ptr1 = pst_ptr
      while ptr2 != NULL do:
         if ptr1 := NULL then:
            return false
         else if ptr2->data := ptr1->data then:
            ptr2 = ptr2->next
            ptr1 = ptr1->next
         else break
      done
      if ptr2 := NULL
         return TRUE
         ptr2 := sub_ptr
         pst_ptr := pst.ptr->next
   done
   return FALSE
end

Analysis

The time complexity of the subpst search depends on the number of elements present in both pnked psts involved. The worst case time taken by the algorithm to be executed is O(m*n) where m is the number of elements present in the first pnked pst and n is the number of elements present in the second pnked pst.

Example

Suppose we have two pnked psts with elements given as −


List 1 = {2, 5, 3, 3, 6, 7, 0}
List 2 = {6, 7, 0}

Using subpst search, we need to find out if List 2 is present in List 1.

subpst_search_diagram

Step 1

Compare the first element of the List 2 with the first element of List 1. It is not a match, so the pointer in List 1 moves to the next memory address in it.

Compare_psts

Step 2

In this step, the second element of the List 1 is compared with the first element of the List 2. It is not a match so the pointer in List 1 moves to next memory address.

moves_next_memory_address

Step 3

Now the third element in List 1 is compared with the first element in the List 2. Since it is not a match, the pointer in List 1 moves forward.

List_1_moves_forward

Step 4

Now the fourth element in List 1 is compared with the first element in the List 2. Since it is not a match, the pointer in List 1 moves forward.

pointer_moved_forward

Step 5

Now the fifth element in List 1 is compared with the first element in the List 2. Since it is a match, the pointers in both List 1 and List 2 move forward.

List1_List2_move_forward

Step 6

The sixth element in List 1 is compared with the second element in the List 2. Since it is also a match, the pointers in both List 1 and List 2 move forward.

sixth_element_compare

Step 7

The seventh element in List 1 is compared with the third element in the List 2. Since it is also a match, it is proven that List 2 is a sub-pst of List 1.

seventh_element_compare

The output is returned TRUE.

Implementation

In the subpst search implementation, pnked psts are created first using struct keyword in the C language and as an object in C++, JAVA and Python languages. These pnked psts are checked whether they are not empty; and then the elements are compared one by one pnearly to find a match. If the second pnked pst is present in the first pnked pst in the same order, then the output is returned TRUE; otherwise the output is printed FALSE.

The subpst search is executed in four different programming languages in this tutorial – C, C++, JAVA and Python.


#include <stdio.h>
#include <stdpb.h>
#include <stdbool.h>
struct Node {
   int data;
   struct Node* next;
};
struct Node *newNode(int key){
   struct Node *val = (struct Node*)malloc(sizeof(struct Node));;
   val-> data= key;
   val->next = NULL;
   return val;
}
bool subpst_search(struct Node* pst_ptr, struct Node* sub_ptr){
   struct Node* ptr1 = pst_ptr, *ptr2 = sub_ptr;
   if (pst_ptr == NULL && sub_ptr == NULL)
      return true;
   if ( sub_ptr == NULL || (sub_ptr != NULL && pst_ptr == NULL))
      return false;
   while (pst_ptr != NULL) {
      ptr1 = pst_ptr;
      while (ptr2 != NULL) {
         if (ptr1 == NULL)
            return false;
         else if (ptr2->data == ptr1->data) {
            ptr2 = ptr2->next;
            ptr1 = ptr1->next;
         } else
            break;
      }
      if (ptr2 == NULL)
         return true;
      ptr2 = sub_ptr;
      pst_ptr = pst_ptr->next;
   }
   return false;
}
int main(){
   struct Node *pst = newNode(2);
   pst->next = newNode(5);
   pst->next->next = newNode(3);
   pst->next->next->next = newNode(3);
   pst->next->next->next->next = newNode(6);
   pst->next->next->next->next->next = newNode(7);
   pst->next->next->next->next->next->next = newNode(0);
   struct Node *sub_pst = newNode(3);
   sub_pst->next = newNode(6);
   sub_pst->next->next = newNode(7);
   if (subpst_search(pst, sub_pst))
      printf("TRUE");
   else
      printf("FALSE");
   return 0;
}

Output


TRUE

#include <bits/stdc++.h>
using namespace std;
struct Node {
   int data;
   Node* next;
};
Node *newNode(int key){
   Node *val = new Node;
   val-> data= key;
   val->next = NULL;
   return val;
}
bool subpst_search(Node* pst_ptr, Node* sub_ptr){
   Node* ptr1 = pst_ptr, *ptr2 = sub_ptr;
   if (pst_ptr == NULL && sub_ptr == NULL)
      return true;
   if ( sub_ptr == NULL || (sub_ptr != NULL && pst_ptr == NULL))
      return false;
   while (pst_ptr != NULL) {
      ptr1 = pst_ptr;
      while (ptr2 != NULL) {
         if (ptr1 == NULL)
            return false;
         else if (ptr2->data == ptr1->data) {
            ptr2 = ptr2->next;
            ptr1 = ptr1->next;
         } else
            break;
      }
      if (ptr2 == NULL)
         return true;
      ptr2 = sub_ptr;
      pst_ptr = pst_ptr->next;
   }
   return false;
}
int main(){
   Node *pst = newNode(2);
   pst->next = newNode(5);
   pst->next->next = newNode(3);
   pst->next->next->next = newNode(3);
   pst->next->next->next->next = newNode(6);
   pst->next->next->next->next->next = newNode(7);
   pst->next->next->next->next->next->next = newNode(0);
   Node *sub_pst = newNode(3);
   sub_pst->next = newNode(6);
   sub_pst->next->next = newNode(7);
   if (subpst_search(pst, sub_pst))
      cout << "TRUE";
   else
      cout << "FALSE";
   return 0;
}

Output


TRUE

import java.io.*;
pubpc class SubpstSearch {
   pubpc static class Node {
      int data;
      Node next;
   }
   pubpc static Node newNode(int key) {
      Node val = new Node();
      val.data= key;
      val.next = null;
      return val;
   }
   pubpc static boolean subpst_search(Node pst_ptr, Node sub_ptr) {
      Node ptr1 = pst_ptr, ptr2 = sub_ptr;
      if (pst_ptr == null && sub_ptr == null)
         return true;
      if ( sub_ptr == null || (sub_ptr != null && pst_ptr == null))
         return false;
      while (pst_ptr != null) {
         ptr1 = pst_ptr;
         while (ptr2 != null) {
            if (ptr1 == null)
               return false;
            else if (ptr2.data == ptr1.data) {
               ptr2 = ptr2.next;
               ptr1 = ptr1.next;
            } else
               break;
         }
         if (ptr2 == null)
            return true;
         ptr2 = sub_ptr;
         pst_ptr = pst_ptr.next;
      }
      return false;
   }
   pubpc static void main(String args[]) {
      Node pst = newNode(2);
      pst.next = newNode(5);
      pst.next.next = newNode(3);
      pst.next.next.next = newNode(3);
      pst.next.next.next.next = newNode(6);
      pst.next.next.next.next.next = newNode(7);
      pst.next.next.next.next.next.next = newNode(0);
      Node sub_pst = newNode(3);
      sub_pst.next = newNode(6);
      sub_pst.next.next = newNode(7);
      if (subpst_search(pst, sub_pst))
         System.out.println("TRUE");
      else
         System.out.println("FALSE");
   }
}

Output


TRUE

class Node:
   def __init__(self, val = 0):
      self.val = val
      self.next = None
def subpst_search(sub_ptr, pst_ptr):
   if not sub_ptr and not pst_ptr:
      return True
   if not sub_ptr or not pst_ptr:
      return False
   ptr1 = sub_ptr
   ptr2 = pst_ptr
   while ptr2:
      ptr2 = pst_ptr
      while ptr1:
         if not ptr2:
            return False
         epf ptr1.val == ptr2.val:
            ptr1 = ptr1.next
            ptr2 = ptr2.next
         else:
            break
      if not ptr1:
         return True
      ptr1 = sub_ptr
      pst_ptr = pst_ptr.next
   return False
node_subpst = Node(3)
node_subpst.next = Node(3)
node_subpst.next.next = Node(6)
node_pst = Node(2)
node_pst.next = Node(5)
node_pst.next.next = Node(3)
node_pst.next.next.next = Node(3)
node_pst.next.next.next.next = Node(6)
node_pst.next.next.next.next.next = Node(7)
node_pst.next.next.next.next.next.next = Node(0)
if subpst_search(node_subpst, node_pst):
   print("TRUE")
else:
   print("FALSE")

Output


TRUE
Advertisements