Print Longest substring without repeating characters
Given a string, print the longest substring without repeating characters. For example, the longest substrings without repeating characters for “ABDEFGABEF” are “BDEFGA” and “DEFGAB”, with length 6. For “BBBB” the longest substring is “B”, with length 1. The desired time complexity is O(n) where n is the length of the string.
Prerequisite: Length of longest substring without repeating characters
Examples:
Input : GEEKSFORGEEKS
Output : EKSFORG
Input : ABDEFGABEF
Output : BDEFGA
Approach:
The idea is to traverse the string and for each already visited character store its last occurrence in a hash table(Here unordered_map is used as a hash with key as character and value as its last position). The variable st stores the starting point of the current substring, maxlen stores the length of maximum length substring, and start stores the starting index of maximum length substring. While traversing the string, check whether the current character is present in the hash table or not.
If it is not present, then store the current character in the hash table with value as the current index. If it is already present in the hash table, this means the current character could repeat in the current substring. For this check, if the previous occurrence of character is before or after the starting point st of the current substring. If it is before st, then only update the value in the hash table. If it is after st, then find the length of current substring currlen as i-st, where i is the current index. Compare currlen with maxlen. If maxlen is less than currlen, then update maxlen as currlen and start as st. After complete traversal of the string, the required the longest substring without repeating characters is from s[start] to s[start+maxlen-1].
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
string findLongestSubstring(string str)
{
int i;
int n = str.length();
int st = 0;
int currlen;
int maxlen = 0;
int start;
unordered_map< char , int > pos;
pos[str[0]] = 0;
for (i = 1; i < n; i++) {
if (pos.find(str[i]) == pos.end())
pos[str[i]] = i;
else {
if (pos[str[i]] >= st) {
currlen = i - st;
if (maxlen < currlen) {
maxlen = currlen;
start = st;
}
st = pos[str[i]] + 1;
}
pos[str[i]] = i;
}
}
if (maxlen < i - st) {
maxlen = i - st;
start = st;
}
return str.substr(start, maxlen);
}
int main()
{
string str = "GEEKSFORGEEKS" ;
cout << findLongestSubstring(str);
return 0;
}
|
Java
import java.util.*;
class GFG{
public static String findLongestSubstring(String str)
{
int i;
int n = str.length();
int st = 0 ;
int currlen = 0 ;
int maxlen = 0 ;
int start = 0 ;
HashMap<Character,
Integer> pos = new HashMap<Character,
Integer>();
pos.put(str.charAt( 0 ), 0 );
for (i = 1 ; i < n; i++)
{
if (!pos.containsKey(str.charAt(i)))
{
pos.put(str.charAt(i), i);
}
else
{
if (pos.get(str.charAt(i)) >= st)
{
currlen = i - st;
if (maxlen < currlen)
{
maxlen = currlen;
start = st;
}
st = pos.get(str.charAt(i)) + 1 ;
}
pos.replace(str.charAt(i), i);
}
}
if (maxlen < i - st)
{
maxlen = i - st;
start = st;
}
return str.substring(start,
start +
maxlen);
}
public static void main(String[] args)
{
String str = "GEEKSFORGEEKS" ;
System.out.print(findLongestSubstring(str));
}
}
|
Python3
def findLongestSubstring(string):
n = len (string)
st = 0
maxlen = 0
start = 0
pos = {}
pos[string[ 0 ]] = 0
for i in range ( 1 , n):
if string[i] not in pos:
pos[string[i]] = i
else :
if pos[string[i]] > = st:
currlen = i - st
if maxlen < currlen:
maxlen = currlen
start = st
st = pos[string[i]] + 1
pos[string[i]] = i
if maxlen < i - st:
maxlen = i - st
start = st
return string[start : start + maxlen]
if __name__ = = "__main__" :
string = "GEEKSFORGEEKS"
print (findLongestSubstring(string))
|
C#
using System;
using System.Collections.Generic;
class GFG{
public static String findlongestSubstring(String str)
{
int i;
int n = str.Length;
int st = 0;
int currlen = 0;
int maxlen = 0;
int start = 0;
Dictionary< char ,
int > pos = new Dictionary< char ,
int >();
pos.Add(str[0], 0);
for (i = 1; i < n; i++)
{
if (!pos.ContainsKey(str[i]))
{
pos.Add(str[i], i);
}
else
{
if (pos[str[i]] >= st)
{
currlen = i - st;
if (maxlen < currlen)
{
maxlen = currlen;
start = st;
}
st = pos[str[i]] + 1;
}
pos[str[i]] = i;
}
}
if (maxlen < i - st)
{
maxlen = i - st;
start = st;
}
return str.Substring(start,
maxlen);
}
public static void Main(String[] args)
{
String str = "GEEKSFORGEEKS" ;
Console.Write(findlongestSubstring(str));
}
}
|
Javascript
<script>
function findLongestSubstring(str)
{
var i;
var n = str.length;
var st = 0;
var currlen;
var maxlen = 0;
var start;
var pos = new Map();
pos.set(str[0], 0);
for ( var i = 1; i < n; i++) {
if (!pos.has(str[i]))
pos.set(str[i],i) ;
else {
if (pos.get(str[i]) >= st) {
currlen = i - st;
if (maxlen < currlen) {
maxlen = currlen;
start = st;
}
st = pos.get(str[i]) + 1;
}
pos.set(str[i], i);
}
}
if (maxlen < i - st) {
maxlen = i - st;
start = st;
}
return str.substr(start,maxlen);
}
var str = "GEEKSFORGEEKS" ;
document.write(findLongestSubstring(str));
</script>
|
Complexity Analysis:
- Time Complexity: O(n)
- Auxiliary Space: O(n)
Another Approach:
- Initialize a hash set to keep track of the characters that have been visited and two variables l and r to mark the left and right ends of the current substring. Also, initialize variables maxL, maxR, and maxStr to keep track of the longest substring found so far.
- Iterate through the string using a while loop until the right pointer r reaches the end of the string.
- Check if the character s[r] is present in the hash set. If it’s not present, insert it into the hash set and move the right pointer r to the next character.
- If the character s[r] is already present in the hash set, it means that the current substring has repeating characters. In this case, remove the character s[l] from the hash set and move the left pointer l to the next character. Repeat this step until the character s[r] is no longer present in the hash set.
- Check if the length of the current substring (r – l + 1) is greater than the length of the longest substring found so far (maxStr). If it is, update maxStr to the length of the current substring, and update maxL and maxR to the left and right pointers l and r.
- Once the loop is finished, use the maxL and maxR indices to print the longest substring without repeating characters.
Below is the implementation of above approach:
C++
#include <iostream>
#include <unordered_set>
using namespace std;
void printLongestSubstring(string s) {
int n = s.size();
int l = 0, r = 0;
unordered_set< char > visited;
int maxStr = 0;
int maxL = 0, maxR = 0;
while (r < n) {
if (visited.find(s[r]) == visited.end()) {
visited.insert(s[r]);
if (r - l + 1 > maxStr) {
maxStr = r - l + 1;
maxL = l;
maxR = r;
}
r++;
}
else {
visited.erase(s[l]);
l++;
}
}
for ( int i = maxL; i <= maxR; i++) {
cout << s[i];
}
cout << endl;
}
int main() {
string str = "GEEKSFORGEEKS" ;
printLongestSubstring(str);
return 0;
}
|
Java
import java.util.HashSet;
public class Main {
public static void printLongestSubstring(String s)
{
int n = s.length();
int l = 0 , r = 0 ;
HashSet<Character> visited = new HashSet<>();
int maxStr = 0 ;
int maxL = 0 , maxR = 0 ;
while (r < n) {
if (!visited.contains(s.charAt(r))) {
visited.add(s.charAt(r));
if (r - l + 1 > maxStr) {
maxStr = r - l + 1 ;
maxL = l;
maxR = r;
}
r++;
}
else {
visited.remove(s.charAt(l));
l++;
}
}
for ( int i = maxL; i <= maxR; i++) {
System.out.print(s.charAt(i));
}
System.out.println();
}
public static void main(String[] args)
{
String str = "GEEKSFORGEEKS" ;
printLongestSubstring(str);
}
}
|
Python3
def printLongestSubstring(s: str ) - > None :
n = len (s)
l, r = 0 , 0
visited = set ()
maxStr = 0
maxL, maxR = 0 , 0
while r < n:
if s[r] not in visited:
visited.add(s[r])
if r - l + 1 > maxStr:
maxStr = r - l + 1
maxL, maxR = l, r
r + = 1
else :
visited.remove(s[l])
l + = 1
print (s[maxL:maxR + 1 ])
str = "GEEKSFORGEEKS"
printLongestSubstring( str )
|
C#
using System;
using System.Collections.Generic;
namespace LongestSubstring
{
class Program
{
static void printLongestSubstring( string s)
{
int n = s.Length;
int l = 0, r = 0;
HashSet< char > visited = new HashSet< char >();
int maxStr = 0;
int maxL = 0, maxR = 0;
while (r < n)
{
if (!visited.Contains(s[r]))
{
visited.Add(s[r]);
if (r - l + 1 > maxStr)
{
maxStr = r - l + 1;
maxL = l;
maxR = r;
}
r++;
}
else
{
visited.Remove(s[l]);
l++;
}
}
for ( int i = maxL; i <= maxR; i++)
{
Console.Write(s[i]);
}
Console.WriteLine();
}
static void Main( string [] args)
{
string str = "GEEKSFORGEEKS" ;
printLongestSubstring(str);
Console.ReadKey();
}
}
}
|
Javascript
function printLongestSubstring(s) {
const n = s.length;
let l = 0;
let r = 0;
const visited = new Set();
let maxStr = 0;
let maxL = 0;
let maxR = 0;
while (r < n) {
if (!visited.has(s[r])) {
visited.add(s[r]);
if (r - l + 1 > maxStr) {
maxStr = r - l + 1;
maxL = l;
maxR = r;
}
r++;
} else {
visited. delete (s[l]);
l++;
}
}
let longestSubstring = '' ;
for (let i = maxL; i <= maxR; i++) {
longestSubstring += s[i];
}
console.log(longestSubstring);
}
const str = "GEEKSFORGEEKS" ;
printLongestSubstring(str);
|
Time Complexity: O(n)
Auxiliary Space: O(1)
Last Updated :
04 Oct, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...