Open In App

Check if Permutation of Pattern is Substring

Last Updated : 16 Jan, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given two strings txt and pat having lowercase letters, the task is to check if any permutation of pat is a substring of txt.

Examples:

Input: txt = "geeks", pat = "eke"
Output: true
Explanation: "eek" is a permutation of "eke" which exists in "geeks".

Input: txt = "programming", pat = "rain"
Output: false
Explanation: No permutation of "rain" exists as a substring in "programming".

[Naive Approach] Checking all possible substrings

The idea is to iterate over all possible substrings of txt having the same length as pat. For each substring of txt, check if pat is a permutation of the substring. Two strings are said to be permutations of each other if they contain the same characters with the same frequencies, but possibly in a different order. So, we can match the frequency of each character in both the strings to check if they are permutations of each other or not.

C++
// C++ Program to check if any permutation of pattern 
// is substring by checking all possible substrings

#include <iostream>
#include <vector>
using namespace std;

const int MAX_CHAR = 26;

bool arePermutations(string &txt, int startIdx, string &pat) {
    vector<int> freq(MAX_CHAR, 0);
    for (int i = 0; i < pat.length(); i++) {

        // Decrement the count of character in txt
        freq[txt[startIdx + i] - 'a'] -= 1;

        // Increment the count of character in pat
        freq[pat[i] - 'a'] += 1;
    }

    for (int i = 0; i < MAX_CHAR; i++) {
        if (freq[i] != 0)
            return false;
    }
    return true;
}

bool search(string &txt, string &pat) {
    int n = txt.length();
    int m = pat.length();

    for (int i = 0; i < n - m + 1; i++) {
      
		// Check if substring in txt starting from i
    	// is a permutation of pat
        if (arePermutations(txt, i, pat))
            return true;
    }

    return false;
}

int main() {
    string txt = "geeks";
    string pat = "eke";
    if (search(txt, pat))
        cout << "true";
    else
        cout << "false";
    return 0;
}
C
// C Program to check if any permutation of pattern
// is substring by checking all possible substrings

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#define MAX_CHAR 26

bool arePermutations(char *txt, int startIdx, char *pat) {
    int freq[MAX_CHAR] = {0};
    int i;
    for (i = 0; i < strlen(pat); i++) {

        // Increment the count of character in txt
        freq[txt[startIdx + i] - 'a'] += 1;

        // Decrement the count of character in pat
        freq[pat[i] - 'a'] -= 1;
    }

    for (i = 0; i < MAX_CHAR; i++) {
        if (freq[i] != 0)
            return false; 
    }
    return true; 
}

int search(char *txt, char *pat) {
    int n = strlen(txt);
    int m = strlen(pat);
    int i;

    for (i = 0; i < n - m + 1; i++) {

        // Check if substring in txt starting from i
        // is a permutation of pat
        if (arePermutations(txt, i, pat))
            return true;
    }

    return false;
}

int main() {
    char txt[] = "geeks";
    char pat[] = "eke";
    if (search(txt, pat))
        printf("true\n");
    else
        printf("false\n");
    return 0;
}
Java
// Java Program to check if any permutation of pattern
// is substring by checking all possible substrings

class GfG {
    static final int MAX_CHAR = 26;
    static boolean arePermutations(String txt, int startIdx, String pat) {
        int[] freq = new int[MAX_CHAR];
        for (int i = 0; i < pat.length(); i++) {

            // Increment the count of character in txt
            freq[txt.charAt(startIdx + i) - 'a'] += 1;

            // Decrement the count of character in pat
            freq[pat.charAt(i) - 'a'] -= 1;
        }

        for (int i = 0; i < MAX_CHAR; i++) {
            if (freq[i] != 0)
                return false;
        }
        return true;
    }

    static boolean search(String txt, String pat) {
        int n = txt.length();
        int m = pat.length();

        for (int i = 0; i < n - m + 1; i++) {

            // Check if substring in txt starting from i
            // is a permutation of pat
            if (arePermutations(txt, i, pat))
                return true;
        }

        return false;
    }

    public static void main(String[] args) {
        String txt = "geeks";
        String pat = "eke";
        if (search(txt, pat))
            System.out.println("true");
        else
            System.out.println("false");
    }
}
Python
# Python Program to check if any permutation of pattern
# is substring by checking all possible substrings

MAX_CHAR = 26

def arePermutations(txt, startIdx, pat):
    freq = [0] * MAX_CHAR
    for i in range(len(pat)):

        # Increment the count of character in txt
        freq[ord(txt[startIdx + i]) - ord('a')] += 1

        # Decrement the count of character in pat
        freq[ord(pat[i]) - ord('a')] -= 1

    for i in range(MAX_CHAR):
        if freq[i] != 0:
            return False
    return True

def search(txt, pat):
    n = len(txt)
    m = len(pat)

    for i in range(n - m + 1):

        # Check if substring in txt starting from i
        # is a permutation of pat
        if arePermutations(txt, i, pat):
            return True

    return False

if __name__ == "__main__":
    txt = "geeks"
    pat = "eke"
    if search(txt, pat):
        print("true")
    else:
        print("false")
C#
// C# Program to check if any permutation of pattern
// is substring by checking all possible substrings

using System;

class GfG {
    const int MAX_CHAR = 26;

    static bool arePermutations(string txt, int startIdx, string pat) {
        int[] freq = new int[MAX_CHAR];
        for (int i = 0; i < pat.Length; i++) {

            // Increment the count of character in txt
            freq[txt[startIdx + i] - 'a'] += 1;

            // Decrement the count of character in pat
            freq[pat[i] - 'a'] -= 1;
        }

        for (int i = 0; i < MAX_CHAR; i++) {
            if (freq[i] != 0)
                return false;
        }
        return true;
    }

    static bool search(string txt, string pat) {
        int n = txt.Length;
        int m = pat.Length;

        for (int i = 0; i < n - m + 1; i++) {

            // Check if substring in txt starting from i
            // is a permutation of pat
            if (arePermutations(txt, i, pat))
                return true;
        }

        return false;
    }

    static void Main() {
        string txt = "geeks";
        string pat = "eke";
        if (search(txt, pat))
            Console.WriteLine("true");
        else
            Console.WriteLine("false");
    }
}
JavaScript
// JavaScript Program to check if any permutation of pattern
// is substring by checking all possible substrings

const MAX_CHAR = 26;

function arePermutations(txt, startIdx, pat) {
    let freq = new Array(MAX_CHAR).fill(0);
    for (let i = 0; i < pat.length; i++) {

        // Increment the count of character in txt
        freq[txt.charCodeAt(startIdx + i) - 'a'.charCodeAt(0)] += 1;

        // Decrement the count of character in pat
        freq[pat.charCodeAt(i) - 'a'.charCodeAt(0)] -= 1;
    }

    for (let i = 0; i < MAX_CHAR; i++) {
        if (freq[i] !== 0)
            return false;
    }
    return true;
}

function search(txt, pat) {
    let n = txt.length;
    let m = pat.length;

    for (let i = 0; i < n - m + 1; i++) {

        // Check if substring in txt starting from i
        // is a permutation of pat
        if (arePermutations(txt, i, pat))
            return true;
    }

    return false;
}

// Driver Code
let txt = "geeks";
let pat = "eke";
if (search(txt, pat))
    console.log("true");
else
    console.log("false");

Output
true

Time Complexity: O(n*m), where n is the length of txt and m is the length of pat.
Auxiliary Space: O(MAX_CHAR), where MAX_CHAR = 26 as txt and pat have lowercase letters only.

[Expected Approach] Using Sliding Window

The idea is similar to the previous approach where we check if pat is a permutation of any substring of txt but instead of comparing each substring from the beginning, we can use Sliding Window Technique and slide a window of the same size as pat. When a new character is added to the window, we increase its frequency by 1 and when a character is removed from the window, we decrease its frequency by 1.

C++
// C++ Program to check if any permutation of string 
// is substring using Sliding Window Technique

#include <iostream>
#include <vector>
using namespace std;

const int MAX_CHAR = 26;

// check if all characters have 0 frequency
bool check(vector<int> &freq) {
	for(int i = 0; i < MAX_CHAR; i++) {
    	if(freq[i] != 0)
            return false;
    }
    return true;
}

bool search(string &txt, string &pat) {
    int n = txt.length();
    int m = pat.length();
  
    vector<int> freq(MAX_CHAR, 0);
  
	// construct the first window
    for(int i = 0; i < m; i++) {
    	freq[txt[i] - 'a'] += 1;
        freq[pat[i] - 'a'] -= 1;
    }
  
	// Check for first window
    if(check(freq))
        return true;
  
    for (int i = m; i < n; i++) {
        // Add the ith character into the window
        freq[txt[i] - 'a'] += 1;

        // Remove the (i - m)th character from the window
        freq[txt[i - m] - 'a'] -= 1;

        // Check for the current window
        if (check(freq))
            return true;
    }

    return false;
}

int main() {
    string txt = "geeks";
    string pat = "eke";
    if (search(txt, pat))
        cout << "true";
    else
        cout << "false";
    return 0;
}
C
// C Program to check if any permutation of string
// is substring using Sliding Window Technique

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#define MAX_CHAR 26

// check if all characters have 0 frequency
bool check(int freq[]) {
    for (int i = 0; i < MAX_CHAR; i++) {
        if (freq[i] != 0)
            return false;
    }
    return true;
}

bool search(char *txt, char *pat) {
    int n = strlen(txt);
    int m = strlen(pat);

    // construct the first window
    int freq[MAX_CHAR] = {0};
    for (int i = 0; i < m; i++) {
        freq[txt[i] - 'a'] += 1;
        freq[pat[i] - 'a'] -= 1;
    }

    // Check for first window
    if (check(freq))
        return true;

    for (int i = m; i < n; i++) {
      
        // Add the ith character into the window
        freq[txt[i] - 'a'] += 1;

        // Remove the (i - m)th character from the window
        freq[txt[i - m] - 'a'] -= 1;

        // Check for the current window
        if (check(freq))
            return true;
    }

    return false;
}

int main() {
    char txt[] = "geeks";
    char pat[] = "eke";
    if (search(txt, pat))
        printf("true");
    else
        printf("false");
    return 0;
}
Java
// Java Program to check if any permutation of string
// is substring using Sliding Window Technique

import java.util.*;

class GfG {
    static final int MAX_CHAR = 26;

    // check if all characters have 0 frequency
    static boolean check(int[] freq) {
        for (int i = 0; i < MAX_CHAR; i++) {
            if (freq[i] != 0)
                return false;
        }
        return true;
    }

    static boolean search(String txt, String pat) {
        int n = txt.length();
        int m = pat.length();

        // construct the first window
        int[] freq = new int[MAX_CHAR];
        Arrays.fill(freq, 0);
        for (int i = 0; i < m; i++) {
            freq[txt.charAt(i) - 'a'] += 1;
            freq[pat.charAt(i) - 'a'] -= 1;
        }

        // Check for first window
        if (check(freq))
            return true;

        for (int i = m; i < n; i++) {

            // Add the ith character into the window
            freq[txt.charAt(i) - 'a'] += 1;

            // Remove the (i - m)th character from the window
            freq[txt.charAt(i - m) - 'a'] -= 1;

            // Check for the current window
            if (check(freq))
                return true;
        }

        return false;
    }

    public static void main(String[] args) {
        String txt = "geeks";
        String pat = "eke";
        if (search(txt, pat))
            System.out.println("true");
        else
            System.out.println("false");
    }
}
Python
# Python Program to check if any permutation of string
# is substring using Sliding Window Technique

MAX_CHAR = 26

# check if all characters have 0 frequency
def check(freq):
    for i in range(MAX_CHAR):
        if freq[i] != 0:
            return False
    return True

def search(txt, pat):
    n = len(txt)
    m = len(pat)

    # construct the first window
    freq = [0] * MAX_CHAR
    for i in range(m):
        freq[ord(txt[i]) - ord('a')] += 1
        freq[ord(pat[i]) - ord('a')] -= 1

    # Check for first window
    if check(freq):
        return True

    for i in range(m, n):

        # Add the ith character into the window
        freq[ord(txt[i]) - ord('a')] += 1

        # Remove the (i - m)th character from the window
        freq[ord(txt[i - m]) - ord('a')] -= 1

        # Check for the current window
        if check(freq):
            return True

    return False

if __name__ == "__main__":
    txt = "geeks"
    pat = "eke"
    if search(txt, pat):
        print("true")
    else:
        print("false")
C#
// C# Program to check if any permutation of string
// is substring using Sliding Window Technique

using System;

class GfG {
    const int MAX_CHAR = 26;

    // check if all characters have 0 frequency
    static bool check(int[] freq) {
        for (int i = 0; i < MAX_CHAR; i++) {
            if (freq[i] != 0)
                return false;
        }
        return true;
    }

    static bool search(string txt, string pat) {
        int n = txt.Length;
        int m = pat.Length;

        // construct the first window
        int[] freq = new int[MAX_CHAR];
        for (int i = 0; i < m; i++) {
            freq[txt[i] - 'a'] += 1;
            freq[pat[i] - 'a'] -= 1;
        }

        // Check for first window
        if (check(freq))
            return true;

        for (int i = m; i < n; i++) {
          
            // Add the ith character into the window
            freq[txt[i] - 'a'] += 1;

            // Remove the (i - m)th character from the window
            freq[txt[i - m] - 'a'] -= 1;

            // Check for the current window
            if (check(freq))
                return true;
        }

        return false;
    }

    static void Main() {
        string txt = "geeks";
        string pat = "eke";
        if (search(txt, pat))
            Console.WriteLine("true");
        else
            Console.WriteLine("false");
    }
}
JavaScript
// JavaScript Program to check if any permutation of string
// is substring using Sliding Window Technique

const MAX_CHAR = 26;

// check if all characters have 0 frequency
function check(freq) {
    for (let i = 0; i < MAX_CHAR; i++) {
        if (freq[i] !== 0)
            return false;
    }
    return true;
}

function search(txt, pat) {
    let n = txt.length;
    let m = pat.length;

    // construct the first window
    let freq = new Array(MAX_CHAR).fill(0);
    for (let i = 0; i < m; i++) {
        freq[txt.charCodeAt(i) - 'a'.charCodeAt(0)] += 1;
        freq[pat.charCodeAt(i) - 'a'.charCodeAt(0)] -= 1;
    }

    // Check for first window
    if (check(freq))
        return true;

    for (let i = m; i < n; i++) {

        // Add the ith character into the window
        freq[txt.charCodeAt(i) - 'a'.charCodeAt(0)] += 1;

        // Remove the (i - m)th character from the window
        freq[txt.charCodeAt(i - m) - 'a'.charCodeAt(0)] -= 1;

        // Check for the current window
        if (check(freq))
            return true;
    }

    return false;
}

// Driver Code
let txt = "geeks";
let pat = "eke";
if (search(txt, pat))
    console.log("true");
else
    console.log("false");

Output
true

Time Complexity: O(n*MAX_CHAR), where n is the length of txt and MAX_CHAR = 26 as txt and pat have lowercase letters only.
Auxiliary Space: O(1)


Next Article

Similar Reads