Open In App

Find the longest Substring of a given String S

Given a string S of length, N. Find the maximum length of any substring of S such that, the bitwise OR of all the characters of the substring is equal to the bitwise OR of the remaining characters of the string. If no such substring exists, print -1.

Examples:



Input: S = “2347”
Output: 3
?Explanation: Consider the substring “234” having length 3. The bitwise OR of the characters of the substring is 2 | 3 | 4 = 7 and the bitwise OR of the remaining characters of the string is 7. Thus, the bitwise OR of all elements of the substring is equal to the bitwise OR of the remaining characters of the string.

Input: S = “124”
Output: -1



Approach: The problem can be solved based on the following observation:

Observations:

  • First compute the bitwise OR of all the characters in the input string, Let M = S1 | S2 | … | SN be the bitwise OR of all the characters.
  • And then use a sliding window approach to iterate over the possible substrings of the string, keeping track of the bitwise OR of the characters in the current substring and comparing it to the bitwise OR of the rest of the string.
  • If the two ORs are equal, the condition for the problem is satisfied and the length of the current substring is compared to the current maximum length.
  • And if the length of the substring is non-zero print the length. Otherwise, print -1. 

Follow the steps mentioned below to implement the idea:

Below is the implementation of the above approach :




// Java implementation of the above approach
import java.io.*;
import java.util.*;
 
public class GFG {
 
    // Function to maximum length of
    // substring of S
    public static void maxLength(int lis[], int n)
    {
        long or = 0;
 
        // Calculate OR of each element
        // of string
        for (int i = 0; i < n; i++) {
            or |= lis[i];
        }
 
        int[] count = new int[32];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < 32; j++) {
                if ((lis[i] & (1L << j)) != 0)
                    count[j]++;
            }
        }
 
        long ans = 0, l = 0, tempOr = 0;
        for (int r = 0; r < n; r++) {
            tempOr |= lis[r];
 
            boolean flag = true;
            for (int i = 0; i < 32; i++) {
                if ((lis[r] & (1L << i)) != 0) {
                    count[i]--;
                    if (count[i] == 0)
                        flag = false;
                }
            }
 
            // If flag = false
            if (!flag) {
                for (; l <= r;) {
                    boolean flag1 = true;
                    for (int i = 0; i < 32; i++) {
                        if ((lis[(int)l] & (1L << i))
                            != 0) {
                            count[i]++;
                        }
                        if (count[i] == 0)
                            flag1 = false;
                    }
                    l++;
                    if (flag1)
                        break;
                }
            }
 
            // If OR of leftover elements and
            // substring elements is equal
            if (tempOr == or) {
 
                ans = Math.max(ans, r - l + 1);
            }
        }
 
        // Print the result
        if (ans != 0)
            System.out.println(ans);
        else
            System.out.println(-1);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        String S = "2347";
        int N = S.length();
        int[] A = new int[N];
        for (int i = 0; i < N; i++) {
            A[i] = S.charAt(i) - '0';
        }
 
        // Function Call
        maxLength(A, N);
    }
}




# Python implementation of the above approach
import math
 
def maxLength(lis, n):
    or_val = 0
 
    # Calculate OR of each element of string
    for i in range(n):
        or_val |= lis[i]
 
    count = [0 for i in range(32)]
    for i in range(n):
        for j in range(32):
            if (lis[i] & (1 << j)) != 0:
                count[j] += 1
 
    ans = 0
    l = 0
    temp_or = 0
    for r in range(n):
        temp_or |= lis[r]
 
        flag = True
        for i in range(32):
            if (lis[r] & (1 << i)) != 0:
                count[i] -= 1
                if count[i] == 0:
                    flag = False
 
        # If flag = false
        if not flag:
            while l <= r:
                flag1 = True
                for i in range(32):
                    if (lis[l] & (1 << i)) != 0:
                        count[i] += 1
                    if count[i] == 0:
                        flag1 = False
                l += 1
                if flag1:
                    break
 
        # If OR of leftover elements and substring elements is equal
        if temp_or == or_val:
            ans = max(ans, r - l + 1)
 
    # Print the result
    if ans != 0:
        print(ans)
    else:
        print(-1)
 
# Driver Code
S = "2347"
N = len(S)
A = [int(S[i]) for i in range(N)]
 
# Function Call
maxLength(A, N)
 
# This code is contributed by lokeshmvs21.




// C# implementation of the above approach
 
using System;
using System.Linq;
 
public class GFG {
 
    // Function to maximum length of
    // substring of S
    static void maxLength(int[] lis, int n)
    {
        long or = 0;
 
        // Calculate OR of each element
        // of string
        for (int i = 0; i < n; i++) {
            or |= lis[i];
        }
 
        int[] count = new int[32];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < 32; j++) {
                if ((lis[i] & (1L << j)) != 0)
                    count[j]++;
            }
        }
 
        long ans = 0, l = 0, tempOr = 0;
        for (int r = 0; r < n; r++) {
            tempOr |= lis[r];
 
            bool flag = true;
            for (int i = 0; i < 32; i++) {
                if ((lis[r] & (1L << i)) != 0) {
                    count[i]--;
                    if (count[i] == 0)
                        flag = false;
                }
            }
 
            // If flag = false
            if (!flag) {
                for (; l <= r;) {
                    bool flag1 = true;
                    for (int i = 0; i < 32; i++) {
                        if ((lis[(int)l] & (1L << i))
                            != 0) {
                            count[i]++;
                        }
                        if (count[i] == 0)
                            flag1 = false;
                    }
                    l++;
                    if (flag1)
                        break;
                }
            }
 
            // If OR of leftover elements and
            // substring elements is equal
            if (tempOr == or) {
                ans = Math.Max(ans, r - l + 1);
            }
        }
 
        // Print the result
        if (ans != 0) {
            Console.WriteLine(ans);
        }
        else {
            Console.WriteLine(-1);
        }
    }
 
    static public void Main()
    {
 
        // Code
        string S = "2347";
        int N = S.Length;
        int[] A = new int[N];
        for (int i = 0; i < N; i++) {
            A[i] = S[i] - '0';
        }
 
        // Function call
        maxLength(A, N);
    }
}
 
// This code is contributed by lokesh.




#include <iostream>
#include <cmath>
#include <string>
 
using namespace std;
 
void maxLength(int lis[], int n)
{
    long long or_result = 0;
 
    // Calculate OR of each element
    // of string
    for (int i = 0; i < n; i++) {
        or_result |= lis[i];
    }
 
    int count[32] = {0};
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 32; j++) {
            if ((lis[i] & (1LL << j)) != 0)
                count[j]++;
        }
    }
 
    long long ans = 0, l = 0, tempOr = 0;
    for (int r = 0; r < n; r++) {
        tempOr |= lis[r];
 
        bool flag = true;
        for (int i = 0; i < 32; i++) {
            if ((lis[r] & (1LL << i)) != 0) {
                count[i]--;
                if (count[i] == 0)
                    flag = false;
            }
        }
 
        // If flag = false
        if (!flag) {
            for (; l <= r;) {
                bool flag1 = true;
                for (int i = 0; i < 32; i++) {
                    if ((lis[l] & (1LL << i)) != 0) {
                        count[i]++;
                    }
                    if (count[i] == 0)
                        flag1 = false;
                }
                l++;
                if (flag1)
                    break;
            }
        }
 
        // If OR of leftover elements and
        // substring elements is equal
        if (tempOr == or_result) {
 
            ans = max(ans, r - l + 1);
        }
    }
 
    // Print the result
    if (ans != 0)
        cout << ans << endl;
    else
        cout << -1 << endl;
}
 
// Driver Code
int main()
{
    string S = "2347";
    int N = S.length();
    int A[N];
    for (int i = 0; i < N; i++) {
        A[i] = S.at(i) - '0';
    }
 
    // Function Call
    maxLength(A, N);
 
    return 0;
}




function maxLength( lis,  n)
{
    let or_result = 0;
 
    // Calculate OR of each element
    // of string
    for (let i = 0; i < n; i++) {
        or_result |= lis[i];
    }
 
    let count=new Array(32).fill(0);
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < 32; j++) {
            if ((lis[i] & (1 << j)) != 0)
                count[j]++;
        }
    }
 
    let ans = 0, l = 0, tempOr = 0;
    for (let r = 0; r < n; r++) {
        tempOr |= lis[r];
 
        let flag = true;
        for (let i = 0; i < 32; i++) {
            if ((lis[r] & (1 << i)) != 0) {
                count[i]--;
                if (count[i] == 0)
                    flag = false;
            }
        }
 
        // If flag = false
        if (!flag) {
            for (; l <= r;) {
                let flag1 = true;
                for (let i = 0; i < 32; i++) {
                    if ((lis[l] & (1 << i)) != 0) {
                        count[i]++;
                    }
                    if (count[i] == 0)
                        flag1 = false;
                }
                l++;
                if (flag1)
                    break;
            }
        }
 
        // If OR of leftover elements and
        // substring elements is equal
        if (tempOr == or_result) {
 
            ans = Math.max(ans, r - l + 1);
        }
    }
 
    // Print the result
    if (ans != 0)
        document.write(ans);
    else
        document.write(-1);
}
 
// Driver Code
let S = "2347";
let N = S.length;
let A=new Array(N);
for (let i = 0; i < N; i++) {
    A[i] = parseInt(S[i]);
}
 
// Function Call
maxLength(A, N);

Output
3

Time Complexity: O(30*N)
Auxiliary Space: O(1)

Related Articles:


Article Tags :