# Design and Analysis - Sublist Search

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

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

For example, consider two linked lists with values {4, 6, 7, 3, 8, 2, 6} and {3, 8, 2}. Sublist search checks whether the values of second list are present in the first linked list. The output is obtained in Boolean values {True, False}. It cannot return the position of the sub-list as the linked list is not an ordered data structure. Note − The output is returned true only if the second linked list is present in the exact same order in the first list.

## Sublist Search Algorithm

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

Procedure for the sublist search algorithm is as follows −

Step 1 − Maintain two pointers, each pointing to one list. These pointers are used to traverse through the linked lists.

Step 2 − Check for the base cases of the linked lists −

• If both linked lists are empty, the output returns true.

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

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

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

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

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

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

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

### Pseudocode

Begin Sublist Search
list_ptr -> points to the first list
sub_ptr -> points to the second list
ptr1 = list_ptr
ptr2 = sub_ptr
if list_ptr := NULL and sub_ptr := NULL then:
return TRUE
end
else if sub_ptr := NULL or sub_ptr != NULL and list_ptr := NULL then:
return FALSE
end
while list_ptr != NULL do:
ptr1 = list_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
list_ptr := list.ptr->next
done
return FALSE
end


### Analysis

The time complexity of the sublist search depends on the number of elements present in both linked lists 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 linked list and n is the number of elements present in the second linked list.

### Example

Suppose we have two linked lists with elements given as −

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


Using sublist search, we need to find out if List 2 is present in List 1. 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. 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. 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. 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. 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. 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. 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-list of List 1. The output is returned TRUE.

## Implementation

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

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

#include <stdio.h>
#include <stdlib.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 sublist_search(struct Node* list_ptr, struct Node* sub_ptr){
struct Node* ptr1 = list_ptr, *ptr2 = sub_ptr;
if (list_ptr == NULL && sub_ptr == NULL)
return true;
if ( sub_ptr == NULL || (sub_ptr != NULL && list_ptr == NULL))
return false;
while (list_ptr != NULL) {
ptr1 = list_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;
list_ptr = list_ptr->next;
}
return false;
}
int main(){
struct Node *list = newNode(2);
list->next = newNode(5);
list->next->next = newNode(3);
list->next->next->next = newNode(3);
list->next->next->next->next = newNode(6);
list->next->next->next->next->next = newNode(7);
list->next->next->next->next->next->next = newNode(0);
struct Node *sub_list = newNode(3);
sub_list->next = newNode(6);
sub_list->next->next = newNode(7);
if (sublist_search(list, sub_list))
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 sublist_search(Node* list_ptr, Node* sub_ptr){
Node* ptr1 = list_ptr, *ptr2 = sub_ptr;
if (list_ptr == NULL && sub_ptr == NULL)
return true;
if ( sub_ptr == NULL || (sub_ptr != NULL && list_ptr == NULL))
return false;
while (list_ptr != NULL) {
ptr1 = list_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;
list_ptr = list_ptr->next;
}
return false;
}
int main(){
Node *list = newNode(2);
list->next = newNode(5);
list->next->next = newNode(3);
list->next->next->next = newNode(3);
list->next->next->next->next = newNode(6);
list->next->next->next->next->next = newNode(7);
list->next->next->next->next->next->next = newNode(0);
Node *sub_list = newNode(3);
sub_list->next = newNode(6);
sub_list->next->next = newNode(7);
if (sublist_search(list, sub_list))
cout << "TRUE";
else
cout << "FALSE";
return 0;
}


### Output

TRUE

import java.io.*;
public class SublistSearch {
public static class Node {
int data;
Node next;
}
public static Node newNode(int key) {
Node val = new Node();
val.data= key;
val.next = null;
return val;
}
public static boolean sublist_search(Node list_ptr, Node sub_ptr) {
Node ptr1 = list_ptr, ptr2 = sub_ptr;
if (list_ptr == null && sub_ptr == null)
return true;
if ( sub_ptr == null || (sub_ptr != null && list_ptr == null))
return false;
while (list_ptr != null) {
ptr1 = list_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;
list_ptr = list_ptr.next;
}
return false;
}
public static void main(String args[]) {
Node list = newNode(2);
list.next = newNode(5);
list.next.next = newNode(3);
list.next.next.next = newNode(3);
list.next.next.next.next = newNode(6);
list.next.next.next.next.next = newNode(7);
list.next.next.next.next.next.next = newNode(0);
Node sub_list = newNode(3);
sub_list.next = newNode(6);
sub_list.next.next = newNode(7);
if (sublist_search(list, sub_list))
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 sublist_search(sub_ptr, list_ptr):
if not sub_ptr and not list_ptr:
return True
if not sub_ptr or not list_ptr:
return False
ptr1 = sub_ptr
ptr2 = list_ptr
while ptr2:
ptr2 = list_ptr
while ptr1:
if not ptr2:
return False
elif ptr1.val == ptr2.val:
ptr1 = ptr1.next
ptr2 = ptr2.next
else:
break
if not ptr1:
return True
ptr1 = sub_ptr
list_ptr = list_ptr.next
return False
node_sublist = Node(3)
node_sublist.next = Node(3)
node_sublist.next.next = Node(6)
node_list = Node(2)
node_list.next = Node(5)
node_list.next.next = Node(3)
node_list.next.next.next = Node(3)
node_list.next.next.next.next = Node(6)
node_list.next.next.next.next.next = Node(7)
node_list.next.next.next.next.next.next = Node(0)
if sublist_search(node_sublist, node_list):
print("TRUE")
else:
print("FALSE")


### Output

TRUE 