Check if a Binary Tree is subtree of another Binary Tree

Last Updated : 1 Aug, 2026

Given the roots of two binary trees, root1 and root2, determine whether the tree rooted at root2 is a subtree of the tree rooted at root1. Return true if there exists a node in the tree rooted at root1 such that the subtree rooted at that node is identical to the tree rooted at root2. Otherwise, return false.

Note: Two binary trees are considered identical if they have the same structure and the same node values.

Examples:       

Input: root1 = [1, 2, 3, N, N, 4], root2 = [3, 4]

Interactive-inorder-4

Output: true
Explanation: In the tree rooted at root1, the subtree starting at node 3 is identical to the tree rooted at root2 (same structure and node values). Hence, root2 is a subtree of root1, so the output is true.

Input: root1 = [26, 10, N, 20, 30, 40, 60], root2 = [26, 10, N, 20, 30, 40, 60]

Interactive-inorder-5

Output: true
Explanation: Both root1 and root2 represent identical trees. So, root2 is a subtree of root1, and the output is true.

Try It Yourself
redirect icon

[Naive Approach] Preorder Traversal with Subtree Matching - O(n * m) Time and O(n + m) Space

The idea is to traverse the main tree (root1) in preorder. At each node, treat it as a potential root and check whether the subtree rooted at this node is identical to root2. The identical check is done by recursively comparing both trees for matching structure and node values. Return true if a match is found at any node, otherwise, continue the traversal.

Working of Approach:

  • Start from every node in the main tree and check whether the subtree rooted at that node is identical to root2.
  • The areIdentical() function recursively compares the current nodes and their left and right subtrees.
  • If an identical subtree is found at any node, return true immediately.
  • Otherwise, recursively search for the subtree in the left and right children of the current node.
  • If no matching subtree exists after traversing the entire tree, return false.
C++
#include <iostream>
using namespace std;

class Node
{
  public:
    int data;
    Node *left;
    Node *right;

    Node(int value)
    {
        data = value;
        left = right = nullptr;
    }
};

// Check if two trees are identical
bool areIdentical(Node *root1, Node *root2)
{

    // Both nodes are null → identical
    if (root1 == nullptr && root2 == nullptr)
        return true;

    // One is null => not identical
    if (root1 == nullptr || root2 == nullptr)
        return false;

    // Check current node and recurse on children
    return (root1->data == root2->data && areIdentical(root1->left, root2->left) &&
            areIdentical(root1->right, root2->right));
}

bool isSubTree(Node *root1, Node *root2)
{

    // Empty subtree => always true
    if (root2 == nullptr)
        return true;

    // Main tree empty but subtree not => false
    if (root1 == nullptr)
        return false;

    // Match found at current node
    if (areIdentical(root1, root2))
        return true;

    // Otherwise, search in left and right
    return isSubTree(root1->left, root2) || isSubTree(root1->right, root2);
}

int main()
{
    // Tree 1
    Node *root1 = new Node(26);
    root1->left = new Node(10);
    // root1->right = nullptr (N)

    root1->left->left = new Node(20);
    root1->left->right = new Node(30);

    root1->left->left->left = new Node(40);
    root1->left->left->right = new Node(60);

    // Tree 2
    Node *root2 = new Node(26);
    root2->left = new Node(10);
    // root2->right = nullptr (N)

    root2->left->left = new Node(20);
    root2->left->right = new Node(30);

    root2->left->left->left = new Node(40);
    root2->left->left->right = new Node(60);

    cout << (isSubTree(root1, root2) ? "true" : "false");

    return 0;
}
Java
import java.util.*;

class Node {
    public int data;
    public Node left;
    public Node right;

    public Node(int value)
    {
        data = value;
        left = right = null;
    }
}

public class GFG {
    // Check if two trees are identical
    public static boolean areIdentical(Node root1,
                                       Node root2)
    {
        // Both nodes are null → identical
        if (root1 == null && root2 == null)
            return true;

        // One is null => not identical
        if (root1 == null || root2 == null)
            return false;

        // Check current node and recurse on children
        return (root1.data == root2.data
                && areIdentical(root1.left, root2.left)
                && areIdentical(root1.right, root2.right));
    }

    public static boolean isSubTree(Node root1, Node root2)
    {
        // Empty subtree => always true
        if (root2 == null)
            return true;

        // Main tree empty but subtree not => false
        if (root1 == null)
            return false;

        // Match found at current node
        if (areIdentical(root1, root2))
            return true;

        // Otherwise, search in left and right
        return isSubTree(root1.left, root2)
            || isSubTree(root1.right, root2);
    }

    public static void main(String[] args)
    {
        // Tree 1
        Node root1 = new Node(26);
        root1.left = new Node(10);
        // root1.right = null (N)

        root1.left.left = new Node(20);
        root1.left.right = new Node(30);

        root1.left.left.left = new Node(40);
        root1.left.left.right = new Node(60);

        // Tree 2
        Node root2 = new Node(26);
        root2.left = new Node(10);
        // root2.right = null (N)

        root2.left.left = new Node(20);
        root2.left.right = new Node(30);

        root2.left.left.left = new Node(40);
        root2.left.left.right = new Node(60);

        System.out.println(
            isSubTree(root1, root2) ? "true" : "false");
    }
}
Python
class Node:
    def __init__(self, value):
        self.data = value
        self.left = None
        self.right = None

# Check if two trees are identical
def areIdentical(root1, root2):
    
    # Both nodes are null → identical
    if root1 is None and root2 is None:
        return True
        
    # One is null => not identical
    if root1 is None or root2 is None:
        return False
        
    # Check current node and recurse on children
    return (root1.data == root2.data and areIdentical(root1.left, root2.left) and areIdentical(root1.right, root2.right))


def isSubTree(root1, root2):
    
    # Empty subtree => always true
    if root2 is None:
        return True
    
    # Main tree empty but subtree not => false
    if root1 is None:
        return False
    
    # Match found at current node
    if areIdentical(root1, root2):
        return True
    
    # Otherwise, search in left and right
    return isSubTree(root1.left, root2) or isSubTree(root1.right, root2)


if __name__ == "__main__":
    
    # Tree 1
    root1 = Node(26)
    root1.left = Node(10)
    # root1.right = None (N)

    root1.left.left = Node(20)
    root1.left.right = Node(30)

    root1.left.left.left = Node(40)
    root1.left.left.right = Node(60)

    # Tree 2
    root2 = Node(26)
    root2.left = Node(10)
    # root2.right = None (N)

    root2.left.left = Node(20)
    root2.left.right = Node(30)

    root2.left.left.left = Node(40)
    root2.left.left.right = Node(60)

    print("true" if isSubTree(root1, root2) else "false")
C#
using System;

public class Node {
    public int data;
    public Node left;
    public Node right;

    public Node(int value)
    {
        data = value;
        left = right = null;
    }
}

public class GFG {
    // Check if two trees are identical
    public static bool AreIdentical(Node root1, Node root2)
    {
        // Both nodes are null → identical
        if (root1 == null && root2 == null)
            return true;

        // One is null => not identical
        if (root1 == null || root2 == null)
            return false;

        // Check current node and recurse on children
        return (root1.data == root2.data
                && AreIdentical(root1.left, root2.left)
                && AreIdentical(root1.right, root2.right));
    }

    public static bool isSubTree(Node root1, Node root2)
    {
        // Empty subtree => always true
        if (root2 == null)
            return true;

        // Main tree empty but subtree not => false
        if (root1 == null)
            return false;

        // Match found at current node
        if (AreIdentical(root1, root2))
            return true;

        // Otherwise, search in left and right
        return isSubTree(root1.left, root2)
            || isSubTree(root1.right, root2);
    }

    public static void Main()
    {
        // Tree 1
        Node root1 = new Node(26);
        root1.left = new Node(10);
        // root1.right = null (N)

        root1.left.left = new Node(20);
        root1.left.right = new Node(30);

        root1.left.left.left = new Node(40);
        root1.left.left.right = new Node(60);

        // Tree 2
        Node root2 = new Node(26);
        root2.left = new Node(10);
        // root2.right = null (N)

        root2.left.left = new Node(20);
        root2.left.right = new Node(30);

        root2.left.left.left = new Node(40);
        root2.left.left.right = new Node(60);

        Console.WriteLine(
            isSubTree(root1, root2) ? "true" : "false");
    }
}
JavaScript
class Node {
    constructor(value)
    {
        this.data = value;
        this.left = null;
        this.right = null;
    }
}

// Check if two trees are identical
function areIdentical(root1, root2)
{
    // Both nodes are null → identical
    if (root1 === null && root2 === null)
        return true;
    // One is null => not identical
    if (root1 === null || root2 === null)
        return false;
    // Check current node and recurse on children
    return (root1.data === root2.data
            && areIdentical(root1.left, root2.left)
            && areIdentical(root1.right, root2.right));
}

function isSubTree(root1, root2)
{
    // Empty subtree => always true
    if (root2 === null)
        return true;
    // Main tree empty but subtree not => false
    if (root1 === null)
        return false;
    // Match found at current node
    if (areIdentical(root1, root2))
        return true;
    // Otherwise, search in left and right
    return isSubTree(root1.left, root2)
           || isSubTree(root1.right, root2);
}

// Driver Code
// Tree 1
let root1 = new Node(26);
root1.left = new Node(10);
// root1.right = null (N)

root1.left.left = new Node(20);
root1.left.right = new Node(30);

root1.left.left.left = new Node(40);
root1.left.left.right = new Node(60);

// Tree 2
let root2 = new Node(26);
root2.left = new Node(10);
// root2.right = null (N)

root2.left.left = new Node(20);
root2.left.right = new Node(30);

root2.left.left.left = new Node(40);
root2.left.left.right = new Node(60);

console.log(isSubTree(root1, root2) ? "true" : "false");

Output
true

[Alternate Approach] Using String Serialisation with Substring Matching - O(n * m) Time and O(n + m) Space

Convert both trees into strings using preorder traversal, and include a special marker (like #) for every null node to preserve the exact structure of the tree. This ensures that different tree structures do not produce the same serialised string. Once both trees are serialised, check if the serialised string of root2 is a substring of the serialised string of root1. If it is found, then root2 is a subtree of root1.

Why this works?

  • Preorder traversal visits nodes in Root -> Left -> Right order, preserving the relative order of all nodes.
  • A # marker is added for every NULL child so that the exact tree structure is also stored.
  • Separators are used between values to avoid incorrect matches (for example, 1 2 should not match 12).
  • Since both values and structure are preserved, every binary tree gets a unique serialized representation.
  • Therefore, the subtree check reduces to a simple substring search between the two serialized strings.
C++
#include <iostream>
#include <string>
using namespace std;

class Node
{
  public:
    int data;
    Node *left;
    Node *right;

    Node(int value)
    {
        data = value;
        left = right = nullptr;
    }
};

// Serialize tree using preorder with null markers
void serialize(Node *root, string &s)
{
    // Null node then add marker
    if (root == nullptr)
    {
        s += " #";
        return;
    }

    // Add current node
    s += " " + to_string(root->data);

    // Recurse on left and right
    serialize(root->left, s);
    serialize(root->right, s);
}

bool isSubTree(Node *root1, Node *root2)
{
    string s1 = "", s2 = "";

    // Serialize both trees
    serialize(root1, s1);
    serialize(root2, s2);

    // Check substring
    return (s1.find(s2) != string::npos);
}

int main()
{
    // Tree 1
    Node *root1 = new Node(26);
    root1->left = new Node(10);
    // root1->right = nullptr (N)

    root1->left->left = new Node(20);
    root1->left->right = new Node(30);

    root1->left->left->left = new Node(40);
    root1->left->left->right = new Node(60);

    // Tree 2
    Node *root2 = new Node(26);
    root2->left = new Node(10);
    // root2->right = nullptr (N)

    root2->left->left = new Node(20);
    root2->left->right = new Node(30);

    root2->left->left->left = new Node(40);
    root2->left->left->right = new Node(60);

    cout << (isSubTree(root1, root2) ? "true" : "false");

    return 0;
}
Java
class Node {
    int data;
    Node left, right;

    Node(int value)
    {
        data = value;
        left = right = null;
    }
}

public class GFG {

    // Serialize tree using preorder with null markers
    static void serialize(Node root, StringBuilder s)
    {

        // Null node then add marker
        if (root == null) {
            s.append(" #");
            return;
        }

        // Add current node
        s.append(" ").append(root.data);

        // Recurse on left and right
        serialize(root.left, s);
        serialize(root.right, s);
    }

    static boolean isSubTree(Node root1, Node root2)
    {
        StringBuilder s1 = new StringBuilder();
        StringBuilder s2 = new StringBuilder();

        // Serialize both trees
        serialize(root1, s1);
        serialize(root2, s2);

        // Check substring
        return s1.toString().contains(s2.toString());
    }

    public static void main(String[] args)
    {

        // Tree 1
        Node root1 = new Node(26);
        root1.left = new Node(10);
        // root1.right = null (N)

        root1.left.left = new Node(20);
        root1.left.right = new Node(30);

        root1.left.left.left = new Node(40);
        root1.left.left.right = new Node(60);

        // Tree 2
        Node root2 = new Node(26);
        root2.left = new Node(10);
        // root2.right = null (N)

        root2.left.left = new Node(20);
        root2.left.right = new Node(30);

        root2.left.left.left = new Node(40);
        root2.left.left.right = new Node(60);

        System.out.println(
            isSubTree(root1, root2) ? "true" : "false");
    }
}
Python
class Node:
    def __init__(self, value):
        self.data = value
        self.left = None
        self.right = None


# Serialize tree using preorder with null markers
def serialize(root):
    # Null node => add marker
    if root is None:
        return ",#,"

    # Add current node and recurse on left and right
    return (
        "," + str(root.data) + "," +
        serialize(root.left) +
        serialize(root.right)
    )


def isSubTree(root1, root2):
    # Serialize both trees
    s1 = serialize(root1)
    s2 = serialize(root2)

    # Check substring
    return s2 in s1


if __name__ == "__main__":
    # Tree 1
    root1 = Node(26)
    root1.left = Node(10)

    root1.left.left = Node(20)
    root1.left.right = Node(30)

    root1.left.left.left = Node(40)
    root1.left.left.right = Node(60)

    # Tree 2
    root2 = Node(26)
    root2.left = Node(10)

    root2.left.left = Node(20)
    root2.left.right = Node(30)

    root2.left.left.left = Node(40)
    root2.left.left.right = Node(60)

    print("true" if isSubTree(root1, root2) else "false")
C#
using System;
using System.Text;

class Node {
    public int data;
    public Node left, right;

    public Node(int value)
    {
        data = value;
        left = right = null;
    }
}

class GFG {
    // Serialize tree using preorder with null markers
    static void Serialize(Node root, StringBuilder s)
    {
        // Null node then add marker
        if (root == null) {
            s.Append(" #");
            return;
        }

        // Add current node
        s.Append(" ").Append(root.data);

        // Recurse on left and right
        Serialize(root.left, s);
        Serialize(root.right, s);
    }

    static bool isSubTree(Node root1, Node root2)
    {
        StringBuilder s1 = new StringBuilder();
        StringBuilder s2 = new StringBuilder();

        // Serialize both trees
        Serialize(root1, s1);
        Serialize(root2, s2);

        // Check substring
        return s1.ToString().Contains(s2.ToString());
    }

    static void Main()
    {
        // Tree 1
        Node root1 = new Node(26);
        root1.left = new Node(10);
        // root1.right = null (N)

        root1.left.left = new Node(20);
        root1.left.right = new Node(30);

        root1.left.left.left = new Node(40);
        root1.left.left.right = new Node(60);

        // Tree 2
        Node root2 = new Node(26);
        root2.left = new Node(10);
        // root2.right = null (N)

        root2.left.left = new Node(20);
        root2.left.right = new Node(30);

        root2.left.left.left = new Node(40);
        root2.left.left.right = new Node(60);

        Console.WriteLine(
            isSubTree(root1, root2) ? "true" : "false");
    }
}
JavaScript
// Definition of a binary tree node
function Node(value) {
    this.data = value;
    this.left = null;
    this.right = null;
}

// Serialize tree using preorder with null markers
function serialize(root) {
    // Null node => add marker
    if (root === null)
        return ",#,";

    // Add current node and recurse on left and right
    return (
        "," +
        root.data +
        "," +
        serialize(root.left) +
        serialize(root.right)
    );
}

// Check if root2 is a subtree of root1
function isSubTree(root1, root2) {
    // Serialize both trees
    let s1 = serialize(root1);
    let s2 = serialize(root2);

    // Check substring
    return s1.includes(s2);
}

// Driver Code

// Tree 1
let root1 = new Node(26);
root1.left = new Node(10);
// root1.right = null (N)

root1.left.left = new Node(20);
root1.left.right = new Node(30);

root1.left.left.left = new Node(40);
root1.left.left.right = new Node(60);

// Tree 2
let root2 = new Node(26);
root2.left = new Node(10);
// root2.right = null (N)

root2.left.left = new Node(20);
root2.left.right = new Node(30);

root2.left.left.left = new Node(40);
root2.left.left.right = new Node(60);

console.log(isSubTree(root1, root2) ? "true" : "false");

Output
true

[Expected Approach] Using String Serialisation with KMP algorithm - O(n + m) Time and O(n + m) Space

This is mainly an optimization over the above approach. The idea is to use KMP algorithm for substring check to ensure that we have overall linear time complexity. Similar to this approach another methods can also be used for substring matching like Boyer–Moore and Trie-based matching.

Working of Approach:

  • Serialize both root1 and root2 using preorder traversal, adding a special marker (#) for every NULL child to preserve the exact tree structure.
  • Construct the LPS (Longest Prefix Suffix) array for the serialized string of root2 to efficiently perform pattern matching.
  • Apply the KMP (Knuth-Morris-Pratt) algorithm to search for the serialized string of root2 within the serialized string of root1.
  • If the serialized string of root2 is found, return true since root2 is a subtree of root1.
  • Otherwise, return false after the KMP search completes without finding a match.

Let us understand with an example:
nput: root1 = [26, 10, N, 20, 30, 40, 60], root2 = [26, 10, N, 20, 30, 40, 60]

  • Serialize both trees using preorder traversal with # for NULL nodes. Both trees produce the same string: 26 10 20 40 # # 60 # # 30 # # #
  • Build the LPS array for the serialized string of root2, which helps KMP skip unnecessary comparisons after a mismatch.
  • Start the KMP search by comparing the serialized string of root2 with that of root1 from left to right.
  • Since all characters match consecutively, KMP finds the complete pattern without any mismatch.
  • As the serialized string of root2 is found in the serialized string of root1, the function returns true.
Interactive-inorder-5
C++
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Node
{
  public:
    int data;
    Node *left;
    Node *right;

    Node(int value)
    {
        data = value;
        left = right = nullptr;
    }
};

// Serialize tree using preorder with null markers
void serialize(Node *root, string &s)
{
    // Null node => add marker
    if (root == nullptr)
    {
        s += " #";
        return;
    }

    // Add current node
    s += " " + to_string(root->data);

    // Recurse on left and right
    serialize(root->left, s);
    serialize(root->right, s);
}

// Build LPS array for KMP
vector<int> buildLPS(string &pattern)
{
    int m = pattern.length();
    vector<int> lps(m, 0);

    int len = 0, i = 1;

    while (i < m)
    {
        if (pattern[i] == pattern[len])
        {
            lps[i++] = ++len;
        }
        else
        {
            if (len != 0)
                len = lps[len - 1];
            else
                i++;
        }
    }

    return lps;
}

// KMP search: check if pattern exists in text
bool kmpSearch(string &text, string &pattern)
{
    vector<int> lps = buildLPS(pattern);

    int i = 0, j = 0;

    while (i < text.length())
    {

        // Characters match => move both
        if (text[i] == pattern[j])
        {
            i++;
            j++;
        }

        // Full pattern matched
        if (j == pattern.length())
            return true;

        // Mismatch after some matches
        else if (i < text.length() && text[i] != pattern[j])
        {
            if (j != 0)
                j = lps[j - 1];
            else
                i++;
        }
    }

    return false;
}

bool isSubTree(Node *root1, Node *root2)
{
    // Serialize both trees
    string s1 = "", s2 = "";
    serialize(root1, s1);
    serialize(root2, s2);

    // Apply KMP to check substring
    return kmpSearch(s1, s2);
}

int main()
{
    // Tree 1
    Node *root1 = new Node(26);
    root1->left = new Node(10);
    // root1->right = nullptr (N)

    root1->left->left = new Node(20);
    root1->left->right = new Node(30);

    root1->left->left->left = new Node(40);
    root1->left->left->right = new Node(60);

    // Tree 2
    Node *root2 = new Node(26);
    root2->left = new Node(10);
    // root2->right = nullptr (N)

    root2->left->left = new Node(20);
    root2->left->right = new Node(30);

    root2->left->left->left = new Node(40);
    root2->left->left->right = new Node(60);

    cout << (isSubTree(root1, root2) ? "true" : "false");

    return 0;
}
Java
import java.util.*;

class Node {
    int data;
    Node left, right;

    Node(int value)
    {
        data = value;
        left = right = null;
    }
}

public class GFG {

    // Serialize tree using preorder with null markers
    static void serialize(Node root, StringBuilder s)
    {
        // Null node => add marker
        if (root == null) {
            s.append(" #");
            return;
        }

        // Add current node
        s.append(" ").append(root.data);

        // Recurse on left and right
        serialize(root.left, s);
        serialize(root.right, s);
    }

    // Build LPS array for KMP
    static int[] buildLPS(String pattern)
    {
        int m = pattern.length();
        int[] lps = new int[m];

        int len = 0, i = 1;

        while (i < m) {
            if (pattern.charAt(i) == pattern.charAt(len)) {
                lps[i++] = ++len;
            }
            else {
                if (len != 0)
                    len = lps[len - 1];
                else
                    i++;
            }
        }

        return lps;
    }

    // KMP search: check if pattern exists in text
    static boolean kmpSearch(String text, String pattern)
    {
        int[] lps = buildLPS(pattern);

        int i = 0, j = 0;

        while (i < text.length()) {

            // Characters match => move both
            if (text.charAt(i) == pattern.charAt(j)) {
                i++;
                j++;
            }

            // Full pattern matched
            if (j == pattern.length())
                return true;

            // Mismatch after some matches
            else if (i < text.length()
                     && text.charAt(i)
                            != pattern.charAt(j)) {
                if (j != 0)
                    j = lps[j - 1];
                else
                    i++;
            }
        }

        return false;
    }

    static boolean isSubTree(Node root1, Node root2)
    {
        StringBuilder s1 = new StringBuilder();
        StringBuilder s2 = new StringBuilder();

        // Serialize both trees
        serialize(root1, s1);
        serialize(root2, s2);

        // Apply KMP to check substring
        return kmpSearch(s1.toString(), s2.toString());
    }

    public static void main(String[] args)
    {

        // Tree 1
        Node root1 = new Node(26);
        root1.left = new Node(10);

        root1.left.left = new Node(20);
        root1.left.right = new Node(30);

        root1.left.left.left = new Node(40);
        root1.left.left.right = new Node(60);

        // Tree 2
        Node root2 = new Node(26);
        root2.left = new Node(10);

        root2.left.left = new Node(20);
        root2.left.right = new Node(30);

        root2.left.left.left = new Node(40);
        root2.left.left.right = new Node(60);

        System.out.println(
            isSubTree(root1, root2) ? "true" : "false");
    }
}
Python
class Node:
    def __init__(self, value):
        self.data = value
        self.left = None
        self.right = None


# Serialize tree using preorder with null markers
def serialize(root, s):

    # Null node => add marker
    if root is None:
        s.append(" #")
        return

    # Add current node
    s.append(" " + str(root.data))

    # Recurse on left and right
    serialize(root.left, s)
    serialize(root.right, s)


# Build LPS array for KMP
def buildLPS(pattern):
    lps = [0] * len(pattern)

    length = 0
    i = 1

    while i < len(pattern):
        if pattern[i] == pattern[length]:
            length += 1
            lps[i] = length
            i += 1
        else:
            if length != 0:
                length = lps[length - 1]
            else:
                i += 1

    return lps


# KMP search
def kmpSearch(text, pattern):
    lps = buildLPS(pattern)

    i = j = 0

    while i < len(text):

        # Match => move both
        if text[i] == pattern[j]:
            i += 1
            j += 1

        # Full match found
        if j == len(pattern):
            return True

        # Mismatch after match
        elif i < len(text) and text[i] != pattern[j]:
            if j != 0:
                j = lps[j - 1]
            else:
                i += 1

    return False


def isSubTree(root1, root2):

    s1 = []
    s2 = []

    # Serialize both trees
    serialize(root1, s1)
    serialize(root2, s2)

    # Convert to string
    str1 = " ".join(s1)
    str2 = " ".join(s2)

    # Apply KMP
    return kmpSearch(str1, str2)


if __name__ == "__main__":
    # Tree 1
    root1 = Node(26)
    root1.left = Node(10)
    root1.left.left = Node(20)
    root1.left.right = Node(30)
    root1.left.left.left = Node(40)
    root1.left.left.right = Node(60)

    # Tree 2
    root2 = Node(26)
    root2.left = Node(10)
    root2.left.left = Node(20)
    root2.left.right = Node(30)
    root2.left.left.left = Node(40)
    root2.left.left.right = Node(60)

    print("true" if isSubTree(root1, root2) else "false")
C#
using System;
using System.Text;

class Node {
    public int data;
    public Node left, right;

    public Node(int value)
    {
        data = value;
        left = right = null;
    }
}

class GFG {
    // Serialize tree using preorder with null markers
    static void Serialize(Node root, StringBuilder s)
    {
        // Null node => add marker
        if (root == null) {
            s.Append(" #");
            return;
        }

        // Add current node
        s.Append(" ").Append(root.data);

        // Recurse on left and right
        Serialize(root.left, s);
        Serialize(root.right, s);
    }

    // Build LPS array for KMP
    static int[] BuildLPS(string pattern)
    {
        int m = pattern.Length;
        int[] lps = new int[m];

        int len = 0, i = 1;

        while (i < m) {
            if (pattern[i] == pattern[len]) {
                lps[i++] = ++len;
            }
            else {
                if (len != 0)
                    len = lps[len - 1];
                else
                    i++;
            }
        }

        return lps;
    }

    // KMP search: check if pattern exists in text
    static bool KMPSearch(string text, string pattern)
    {
        int[] lps = BuildLPS(pattern);

        int i = 0, j = 0;

        while (i < text.Length) {
            // Characters match => move both
            if (text[i] == pattern[j]) {
                i++;
                j++;
            }

            // Full pattern matched
            if (j == pattern.Length)
                return true;

            // Mismatch after some matches
            else if (i < text.Length
                     && text[i] != pattern[j]) {
                if (j != 0)
                    j = lps[j - 1];
                else
                    i++;
            }
        }

        return false;
    }

    static bool isSubTree(Node root1, Node root2)
    {
        StringBuilder s1 = new StringBuilder();
        StringBuilder s2 = new StringBuilder();

        // Serialize both trees
        Serialize(root1, s1);
        Serialize(root2, s2);

        // Apply KMP to check substring
        return KMPSearch(s1.ToString(), s2.ToString());
    }

    static void Main()
    {
        // Tree 1
        Node root1 = new Node(26);
        root1.left = new Node(10);

        root1.left.left = new Node(20);
        root1.left.right = new Node(30);

        root1.left.left.left = new Node(40);
        root1.left.left.right = new Node(60);

        // Tree 2
        Node root2 = new Node(26);
        root2.left = new Node(10);

        root2.left.left = new Node(20);
        root2.left.right = new Node(30);

        root2.left.left.left = new Node(40);
        root2.left.left.right = new Node(60);

        Console.WriteLine(
            isSubTree(root1, root2) ? "true" : "false");
    }
}
JavaScript
// Definition of a binary tree node
function Node(value)
{
    this.data = value;
    this.left = null;
    this.right = null;
}

// Serialize tree using preorder with null markers
function serialize(root)
{
    // Null node => add marker
    if (root === null)
        return " #";

    // Add current node and recurse on left and right
    return (" " + root.data + serialize(root.left)
            + serialize(root.right));
}

// Build LPS array for KMP
function buildLPS(pattern)
{
    let m = pattern.length;
    let lps = new Array(m).fill(0);

    let len = 0;
    let i = 1;

    while (i < m) {
        if (pattern[i] === pattern[len]) {
            lps[i] = ++len;
            i++;
        }
        else {
            if (len !== 0)
                len = lps[len - 1];
            else
                i++;
        }
    }

    return lps;
}

// KMP search: check if pattern exists in text
function kmpSearch(text, pattern)
{
    let lps = buildLPS(pattern);

    let i = 0;
    let j = 0;

    while (i < text.length) {
        if (text[i] === pattern[j]) {
            i++;
            j++;
        }

        // Full pattern matched
        if (j === pattern.length)
            return true;

        // Mismatch after some matches
        else if (i < text.length
                 && text[i] !== pattern[j]) {
            if (j !== 0)
                j = lps[j - 1];
            else
                i++;
        }
    }

    return false;
}

// Check if root2 is a subtree of root1
function isSubTree(root1, root2)
{
    // Serialize both trees
    let s1 = serialize(root1);
    let s2 = serialize(root2);

    // Apply KMP to check substring
    return kmpSearch(s1, s2);
}

// Driver Code

// Tree 1
let root1 = new Node(26);
root1.left = new Node(10);
root1.left.left = new Node(20);
root1.left.right = new Node(30);
root1.left.left.left = new Node(40);
root1.left.left.right = new Node(60);

// Tree 2
let root2 = new Node(26);
root2.left = new Node(10);
root2.left.left = new Node(20);
root2.left.right = new Node(30);
root2.left.left.left = new Node(40);
root2.left.left.right = new Node(60);

console.log(isSubTree(root1, root2) ? "true" : "false");

Output
true
Comment