Length of the longest substring without repeating characters

Given a string, find the length of 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. For “GEEKSFORGEEKS”, there are two longest substrings shown in the below diagrams, with length 7.



The desired time complexity is O(n) where n is the length of the string.

Method 1 (Simple)
We can consider all substrings one by one and check for each substring whether it contains all unique characters or not. There will be n*(n+1)/2 substrings. Whether a substirng contains all unique characters or not can be checked in linear time by scanning it from left to right and keeping a map of visited characters. Time complexity of this solution would be O(n^3).

Method 2 (Linear Time)
Let us talk about the linear time solution now. This solution uses extra space to store the last indexes of already visited characters. The idea is to scan the string from left to right, keep track of the maximum length Non-Repeating Character Substring (NRCS) seen so far. Let the maximum length be max_len. When we traverse the string, we also keep track of length of the current NRCS using cur_len variable. For every new character, we look for it in already processed part of the string (A temp array called visited[] is used for this purpose). If it is not present, then we increase the cur_len by 1. If present, then there are two cases:

a) The previous instance of character is not part of current NRCS (The NRCS which is under process). In this case, we need to simply increase cur_len by 1.
b) If the previous instance is part of the current NRCS, then our current NRCS changes. It becomes the substring staring from the next character of previous instance to currently scanned character. We also need to compare cur_len and max_len, before changing current NRCS (or changing cur_len).

Implementation

C/C++

// C/C++ program to find the length of the longest substring
// without repeating characters
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define NO_OF_CHARS 256

int min(int a, int b);

int longestUniqueSubsttr(char *str)
{
    int n = strlen(str);
    int cur_len = 1;  // lenght of current substring
    int max_len = 1;  // result
    int prev_index;  //  previous index
    int i;
    int *visited = (int *)malloc(sizeof(int)*NO_OF_CHARS);

    /* Initialize the visited array as -1, -1 is used to
       indicate that character has not been visited yet. */
    for (i = 0; i < NO_OF_CHARS;  i++)
        visited[i] = -1;

    /* Mark first character as visited by storing the index
       of first   character in visited array. */
    visited[str[0]] = 0;

    /* Start from the second character. First character is
       already processed (cur_len and max_len are initialized
       as 1, and visited[str[0]] is set */
    for (i = 1; i < n; i++)
    {
        prev_index =  visited[str[i]];

        /* If the currentt character is not present in the
           already processed substring or it is not part of
           the current NRCS, then do cur_len++ */
        if (prev_index == -1 || i - cur_len > prev_index)
            cur_len++;

        /* If the current character is present in currently
           considered NRCS, then update NRCS to start from
           the next character of previous instance. */
        else
        {
            /* Also, when we are changing the NRCS, we
               should also check whether length of the
               previous NRCS was greater than max_len or
               not.*/
            if (cur_len > max_len)
                max_len = cur_len;

            cur_len = i - prev_index;
        }

        // update the index of current character
        visited[str[i]] = i;
    }

    // Compare the length of last NRCS with max_len and
    // update max_len if needed
    if (cur_len > max_len)
        max_len = cur_len;

    free(visited); // free memory allocated for visited
    return max_len;
}

/* A utility function to get the minimum of two integers */
int min(int a, int b)
{
    return (a>b)?b:a;
}

/* Driver program to test above function */
int main()
{
    char str[] = "ABDEFGABEF";
    printf("The input string is %s \n", str);
    int len =  longestUniqueSubsttr(str);
    printf("The length of the longest non-repeating "
           "character substring is %d", len);
    return 0;
}

Python

# Python program to find the length of the longest substring
# without repeating characters
NO_OF_CHARS = 256

def longestUniqueSubsttr(string):
    n = len(string)
    cur_len = 1        # To store the lenght of current substring
    max_len = 1        # To store the result
    prev_index = 0    # To store the previous index
    i = 0

    # Initialize the visited array as -1, -1 is used to indicate
    # that character has not been visited yet.
    visited = [-1] * NO_OF_CHARS

    # Mark first character as visited by storing the index of
    # first character in visited array.
    visited[ord(string[0])] = 0

    # Start from the second character. First character is already
    # processed (cur_len and max_len are initialized as 1, and
    # visited[str[0]] is set
    for i in xrange(1,n):
        prev_index = visited[ord(string[i])]

        # If the currentt character is not present in the already
        # processed substring or it is not part of the current NRCS,
        # then do cur_len++
        if prev_index == -1 or (i - cur_len > prev_index):
            cur_len+=1

        # If the current character is present in currently considered
        # NRCS, then update NRCS to start from the next character of
        # previous instance.
        else:
            # Also, when we are changing the NRCS, we should also
            # check whether length of the previous NRCS was greater
            # than max_len or not.
            if cur_len > max_len:
                max_len = cur_len

            cur_len = i - prev_index

        # update the index of current character
        visited[ord(string[i])] = i

    # Compare the length of last NRCS with max_len and update
    # max_len if needed
    if cur_len > max_len:
        max_len = cur_len

    return max_len

# Driver program to test the above function
string = "ABDEFGABEF"
print "The input string is " + string
length = longestUniqueSubsttr(string)
print ("The length of the longest non-repeating character" +
       " substring is " + str(length))

# This code is contributed by Bhavya Jain


Output

  The input string is ABDEFGABEF
  The length of the longest non-repeating character substring is 6

Time Complexity: O(n + d) where n is length of the input string and d is number of characters in input string alphabet. For example, if string consists of lowercase English characters then value of d is 26.
Auxiliary Space: O(d)
Algorithmic Paradigm: Dynamic Programming

As an exercise, try the modified version of the above problem where you need to print the maximum length NRCS also (the above program only prints length of it).

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.









Writing code in comment? Please use code.geeksforgeeks.org, generate link and share the link here.

  • Arnab

    package Geeks;

    import java.lang.*;

    import java.util.*;

    class longestSubstr{

    public static void main(String[] args){

    String s=”ABDEFGABEF”;

    int ans=calc(s);

    System.out.println(“Max nonrepeating seq= “+ans);

    }

    public static int calc(String s)

    {

    int n=s.length();

    int max=1;

    if(n==1)

    return 1;

    if(n==2)

    {

    if(s.charAt(0)==s.charAt(1)) return 1;

    else return 2;

    }

    String s1=s;

    String a=s.charAt(n-1)+””;

    s1=s1.replace(a,””);

    // System.out.println(s+” “+(n-2)+” “+s.substring(0,n-1));

    max=Math.max(calc(s.substring(0,n-1)),(calc(s1)+1));

    return max;

    }

    }

  • Ashish

    The longest NRCS can be printed by code at below link:
    http://ideone.com/FFQRkw

    Plz point out if any mistake…….

  • Mohaan

    We can print and count like below.. If any mistake please specify…

    http://ideone.com/IFZygQ

  • Srikant Aggarwal

    This is giving wrong answer for ABCDEFCGHIJB

    • mccullum

      its 9 correct

  • shan

    A very simple solution to check and find longest substring is

    #include

    using namespace std;

    int main()

    {

    char s[]=”geeksforgeeks”;

    bool visited[26]={false};

    int max=INT_MIN,count=0,i=0;

    while(s[i]!=”)

    {

    if(visited[s[i]-‘a’]==false)

    {

    visited[s[i]-‘a’]=true;

    count++;

    }

    else{

    memset(visited,false,sizeof(visited));

    count=1;

    visited[s[i]-‘a’]=true;

    }

    if(count>max)

    max=count;

    i++;

    }

    cout<<max;

    return 0;

    }

  • prashant jha

    here is the 0(nlogn) complexity using divide and conquer approach
    http://ideone.com/eDWtc8

  • Yogendra Singh Vimal

    #include

    #include

    #include

    #define MAX 256

    int lsubstring(char *s)

    {

    int count[MAX][2]={{0}};

    int MLEN=0,CLEN=0,i,j,ptr=0;

    for(i=0;*(s+i);i++)

    {

    if(count[*(s+i)][0]==0)

    {

    count[*(s+i)][0]=1;

    count[*(s+i)][1]=i;

    CLEN++;

    }

    else

    {

    if(count[*(s+i)][1]>=ptr)

    {

    if(CLEN>MLEN)

    MLEN=CLEN;

    ptr=count[*(s+i)][1]+1;

    CLEN=i-count[*(s+i)][1];

    count[*(s+i)][1]=i;

    }

    else

    {

    count[*(s+i)][1]=i;

    CLEN++;

    }

    }

    }

    return (CLEN>MLEN)?CLEN:MLEN;

    }

    int main()

    {

    char *s=”abcdaefghijklmnopqrstuvwxyz”;

    printf(“nInput String is %s”,s);

    int len=lsubstring(s);

    printf(“nThe length of longest substring is %d”,len);

    return 0;

    }

  • Harjit Singh

    This is wrong. We have to use array of size equal to string size in stead of 256. It is giving wrong result.

  • navneet goel

    In the 2nd method program, run for the input string “geeksforkgeeks”. here it shows output as “The length of the longest non-repeating character substring is 7″ though here longest non repeating character substring is 5 (from k of geeks to k of fork).
    Please correct me if i am wrong.

    • chen

      sforkge

  • vikram

    reposting….
    Code for printing the longest unique sub string. Also prints all the unique strings of same length.
    Please correct me, if something is wrong. Also please share if someone has better code.


    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    int LongestUniqueSubString(char *str)
    {
    if(str == 0)
    return 0;
    cout << "Input string = " << str << "n";
    /*save the latest index at the character position*/
    int charIdx[256];
    for(int i=0; i = s) {
    if(e-s+1 == fc) { /*track equal longest unique strings*/
    ++fi;
    fs[fi] = s;
    fe[fi] = e;
    }else if(e-s+1 > fc) { /*update longest unique string*/
    fc=e-s+1;
    fs[0]=s;
    fe[0]=e;
    fi=0;
    }
    s = charIdx + 1; //move the start mark to next position.
    }
    charIdx = i;
    e=i;
    }
    if(e-s+1 == fc) {
    ++fi;
    fs[fi] = s;
    fe[fi] = e;
    }else if(e-s+1 > fc) {
    fc=e-s+1;
    fs[0]=s;
    fe[0]=e;
    fi=0;
    }
    cout << "The longest unique substring = n";
    for(int i=0; i <= fi; i++) {
    for(int j=fs[i]; j <= fe[i]; j++) {
    cout << str[j];
    }
    cout << "n";
    }
    cout << "length = " << fc << "n";
    cout << "-------------------------------------n";
    return fc;
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
    char *p = "ABCDEFGH";
    LongestUniqueSubString(p);
    p = "ABDEFGALMF";
    LongestUniqueSubString(p);
    p = "GEEKSFORGEEKS";
    LongestUniqueSubString(p);
    p = "AAAA";
    LongestUniqueSubString(p);
    p = "ABCABCABC";
    LongestUniqueSubString(p);
    p = "ABCDECQWERTYU";
    LongestUniqueSubString(p);
    p = "BBACDBV";
    LongestUniqueSubString(p);
    return 0;
    }

  • vikram

    Code for printing the longest unique sub strings.
    Please correct me, if something wrong. Please share, if someone has the code for printing the sub string.

    #include "stdafx.h"

    #include

    using namespace std;

    int LongestUniqueSubString(char *str)

    {

    if(str == 0)

    return 0;

    cout << "Input string = " << str << "n";

    /*save the latest index at the character position*/

    int charIdx[256];

    for(int i=0; i = s) {

    if(e-s+1 == fc) { /*track equal longest unique strings*/

    ++fi;

    fs[fi] = s;

    fe[fi] = e;

    }else if(e-s+1 > fc) { /*update longest unique string*/

    fc=e-s+1;

    fs[0]=s;

    fe[0]=e;

    fi=0;

    }

    s = charIdx + 1; //move the start mark to next position.

    }

    charIdx = i;

    e=i;

    }

    if(e-s+1 == fc) {

    ++fi;

    fs[fi] = s;

    fe[fi] = e;

    }else if(e-s+1 > fc) {

    fc=e-s+1;

    fs[0]=s;

    fe[0]=e;

    fi=0;

    }

    cout << "The longest unique substring = n";

    for(int i=0; i <= fi; i++) {

    for(int j=fs[i]; j <= fe[i]; j++) {

    cout << str[j];

    }

    cout << "n";

    }

    cout << "length = " << fc << "n";

    cout << "-------------------------------------n";

    return fc;

    }

    int _tmain(int argc, _TCHAR* argv[])

    {

    char *p = "ABCDEFGH";

    LongestUniqueSubString(p);

    p = "ABDEFGALMF";

    LongestUniqueSubString(p);

    p = "GEEKSFORGEEKS";

    LongestUniqueSubString(p);

    p = "AAAA";

    LongestUniqueSubString(p);

    p = "ABCABCABC";

    LongestUniqueSubString(p);

    p = "ABCDECQWERTYU";

    LongestUniqueSubString(p);

    return 0;

    }

  • vishal

    O(n) time and O(26) space

     
    void initialise(int a[] , int n)
    {
        int i =0;
        for(i = 0 ; i < n ;++i)
            a[i]  = 0;
    }
    int main()
    {
            char arr[] = "GeeksforGeeks";
            int count[26] = {0};
            int i =0;
            int max = 0 , sum = 0;
            while( i < 13)
            {
                    arr[i] = toupper(arr[i]);
                    if( count[arr[i] - 65] == 0)
                    {
                            ++sum;
                            count[arr[i] -65] = 1;
                    }
                    else
                    {
                        if( sum > max)
                            max = sum;
                         sum = 0;
                         initialise(count , 26);
                         --i;
                    }
    
                    ++i;
            }
            printf("The maximum : %d\n" , max);
            return 0;
    }
    
     
    • timus

      try this as input: “asdfgauvwx”
      It’ll give ans as 5, instead of 9

  • vishal

    O(n) solution with o(26) space

     
    void initialise(int a[] , int n)
    {
        int i =0;
        for(i = 0 ; i < n ;++i)
            a[i]  = 0;
    }
    int main()
    {
            char arr[] = "GeeksforGeeks";
            int count[26] = {0};
            int i =0;
            int max = 0 , sum = 0;
            while( i < 13)
            {
                    arr[i] = toupper(arr[i]);
                    if( count[arr[i] - 65] == 0)
                    {
                            ++sum;
                            count[arr[i] -65] = 1;
                    }
                    else
                    {
                        if( sum > max)
                            max = sum;
                         sum = 0;
                         initialise(count , 26);
                         --i;
                    }
    
                    ++i;
            }
            printf("The maximum : %d\n" , max);
            return 0;
    }
    
     
    • Anonymous

      Your algorithm fails for this case:
      “GEEKSFORGEEKSXYZRLBHA”
      Output is 7 but it should be 11
      You should update max value every time new letter is added to NRCS

       
      #include <iostream>
      #include <cstring>
      #include <cstdio>
      using namespace std;
      
      void initialise(int a[] , int n)
      {
          int i =0;
          for(i = 0 ; i < n ;++i)
              a[i]  = 0;
      }
      int main()
      {
              char arr[] = "GEEKSFORGEEKSXYZRLBHA";
              int count[26] = {0};
              int i =0;
              int max = 0 , sum = 0;
              char n;
              while( i < strlen(arr))
              {
                  n = arr[i];
                      if( count[arr[i] - 65] == 0)
                      {
                              ++sum;
                              count[arr[i] -65] = 1;
                              if( sum > max) max = sum;
                      }
                      else
                      {
                          if( sum > max) max = sum;
                           sum = 0;
                           initialise(count , 26);
                           --i;
                      }
      
                      ++i;
              }
              printf("The maximum : %d\n" , max);
              return 0;
      }
      
       
      • vishal

        Agreed I missed a case where the longest string is terminated at the end . Thank You for Pointing this out

         
        
         
  • vivek

    /*
    #include
    #include
    void undo(int a[],char *s,int n)
    {
    int i;
    for(i=0;i<=n;i++)
    a[s[i]]=0;
    }
    int len(char *str)
    {
    int n =strlen(str);
    int a[256]={0};
    int i=0;
    int maxcount=0;
    int index=0;
    int count=0;
    while(i<n)
    {
    count=0;
    while(!a[str[i]]&&i<n)
    {
    a[str[i]]++;
    count++;
    i++;
    }
    if(i!=n)
    {
    undo(a,str,i);index=i;
    }
    if(maxcount<count)
    {
    maxcount=count;
    }
    count=0;
    }
    printf("%c\n",str[index]);
    return maxcount;
    }
    int main()
    {

    char s[]="ABCDEFGHIJAAKLMNOPQBARSTUVWXYZ";
    printf("%d\n",len(s));
    return 0;
    }

    */

  • The King

    #include
    #include
    #define mchar 256

    int main()
    {
    int i,j=0, len=0,max=0,*temp=NULL;
    char str[20];
    gets(str);

    temp = (int *) calloc(sizeof(int) , mchar);

    for(i=0;*(str+i);i++)
    {
    if(temp[*(str+i)] == 0)
    {
    len++;
    temp[*(str+i)]=1;
    }
    else
    {
    for(j=len-1; j>=0 ; j–)
    temp[*(str+j)] = 0;

    temp[*(str+i)]=1;

    if(len > max)
    max = len;
    len = 1;
    }
    }
    printf(“The maximum substring is=%d”, max);
    getchar();
    return 0;
    }

  • me.abhinav

    Another O(n) solution.
    < >

     
    #include <iostream>
    #define SIZ 100
    #define index(c) c-'a'
    
    using namespace std;
    
    void process(char *str){
    	int i, j, start, end, maxLen = -1, curLen;
    	bool present[26];
    	for(i=0 ; i<26 ; i++)
    		present[i] = false;
    
    	present[index(str[0])] = true;
    	start = end = i = 0; curLen = j = 1;
    	while(str[j]){
    		if(!present[index(str[j])]){
    			curLen++;
    		}else{
    			while(present[index(str[j])]){
    				present[index(str[i])] = false;
    				i++;
    				curLen--;
    			}
    		}
    		if(curLen>maxLen){
    			maxLen = curLen;
    			start = i;
    			end = j;
    		}
    		present[index(str[j])] = true;
    		j++;
    	}
    	char *res = new char[end-start+2];
    	for(i=start ; i<=end ; i++)
    		res[i-start] = str[i];
    	res[i-start] = '\0';
    	cout<<start<<" "<<end<<" "<<res<<"\n\n";
    }
    
    int main(){
    	char str[SIZ];
    	char *res;
    
    	while(1){
    		cin>>str;
    		process(str);
    	}
    
    	return 0;
    }
    
     
    • me.abhinav

      EXPECTING ONLY LOWER CASE ENGLISH ALPHABETS

  • pritybhudolia

    I think this program is very simple and works in O(n) Complexity. I have used hashing.Correct me if anything is wrong. :)

    #include
    #include
    int longestUniqueSubsttr(char str[])
    {
    int hash[256]={0};
    int start=0,max=0,i=0,j=0,end=0,begin=0;
    for(i=0;imax)
    {
    max=end-start;
    begin=start;
    j=end;

    }
    }
    hash[str[i]]=1;
    }
    printf(“The longest non-repeating character substring is :”);
    for(start=begin;start<=j;start++) printf(“%c”,str[start]); return max; } int main() { char str[] = “GEEKSFORGEEKS”; printf(“The input string is :%s \n”, str); int len = longestUniqueSubsttr(str); printf(“\nThe length of the longest non-repeating character substring is :%d”, len); getchar(); return 0; }

    • pritybhudolia

      Previous code is not pasted properly. I have used hashing.Try this :)

       
      #include<stdio.h>
      #include<conio.h>
      int longestUniqueSubsttr(char str[])
      {
           int hash[256]={0};
           int start=0,max=0,i=0,j=0,end=0,begin=0;
           for(i=0;i<strlen(str);i++)
           {
                 if(hash[str[i]]==1) 
                 {  
                       start=end;
                       end=i;
                       if((end-start)>max)
                       {
                           max=end-start;
                           begin=start;
                           j=end;                                                                      
                       }
                 }
                 hash[str[i]]=1;
           }
           printf("The longest non-repeating character substring is :");
           for(start=begin;start<=j;start++) printf("%c",str[start]);
           return max;
      }
      
      int main()
      {
          char str[] = "GEEKSFORGEEKS";
          printf("The input string is :%s \n", str);
          int len =  longestUniqueSubsttr(str);
          printf("\nThe length of the longest non-repeating character substring is :%d", len);
       
          getchar();
          return 0;
      }
      
       
      • Akash

        Hi, I guess the program returns length as 0 if all the characters in the input string are unique. This is because you are entering the if statement where the max variable is updated only when you find that there is a repeating character.

        Also, in current scenario I guess you have missed to check whether the repeated character that you are checking is included in length of NRCS or not. That is why its giving the output of length of longest NRCS as 6 for the input string “GEEKS FORGEEKS”.

        I guess this might help. Please correct me if wrong.

         
        /* Paste your code here (You may delete these lines if not writing code) */
         
      • MVN Murthy

        Take This Input – abcabcdabcdeabcdefga
        Output should be – abcdefg

        Your output is – abca

        because you are not maintaining hash table.when encounter some duplicates you should change hash table respective values.

        Following is the Modification. Correct me if i m wrong.

        #include

        using namespace std;

        void check(char *s,int n)
        {
        int *count,i,begin,end,m=-100,s_w;
        s_w = begin = end = 0;
        count = new int [256];

        for(i=0;i m)
        { m = i-begin;s_w = begin;end = i-1;}

        while(count[s[i]]) {count[s[begin]]=0; begin++;}
        begin = i;

        }

        count[s[i]]++;

        }

        // check whether all characters in string are non repeating
        if(i-begin-1 > m)
        { m = i-begin;s_w = begin;end = i-1;}

        for(i = s_w;i<=end ;i++) cout<<s[i];

        cout<<endl;
        cout<<"Length of the non repeating string is: "<<end-s_w+1;
        cout<<endl;

        }

        int main (int argc, char const* argv[])
        {
        string s;
        getline(cin,s);

        check(&s[0],s.length());
        return 0;
        }

  • Prateek Sharma

    python code with o(n) time complexity based on approach similar to KMP algo….

     
    storingList =[]
    def recursion(list1,tempArray,initial,i,len1):
        if i == len1:
            storingList.append(list1[initial:i])
            return 0
        else:  
            if tempArray[list1[i]][0] !=1:
                tempArray[list1[i]] = [1,i]
                i = i+1
                recursion(list1,tempArray,initial,i,len1)
            else:
                storingList.append(list1[initial:i])
                initial = tempArray[list1[i]][1]+1
                tempArray[list1[i]][1]  =i
                i = i+1
                recursion(list1,tempArray,initial,i,len1)
    def recursion1(list1,tempArray,initial,i,len1):
        if i == len1:
            storingList.append(list1[initial:i])
            return 0
        else:  
            if tempArray[ord(list1[i])][0] !=1:
                tempArray[ord(list1[i])] = [1,i]
                i = i+1
                recursion1(list1,tempArray,initial,i,len1)
            else:
                storingList.append(list1[initial:i])
                initial = tempArray[ord(list1[i])][1]+1
                tempArray[ord(list1[i])][1]  =i
                i = i+1
                recursion1(list1,tempArray,initial,i,len1)
            
    def longestSubstring(s,bool):
        initial = 0
        list2 =[]
        list1 = list(s)
        if bool == True:
            for i in list1:
                list2.append(int(i))
            list1 = list2    
        len1 = len(s)
        if bool == True:
            maxi = max(list1)
        else:
            maxi = ord(max(list1))    
        tempArray = [[0,0] for _dummy in xrange(maxi+1)]
        if bool == True:
            recursion(list1,tempArray,initial,0,len1)
        else:
            recursion1(list1,tempArray,initial,0,len1)
        maxi = 0
        for i in storingList:
            if len(i)>maxi:
                maxi = len(i)
        for i in storingList:
            if len(i) == maxi:
                if bool == True:
                    list3 =[]
                    for j in i:
                        list3.append(str(j))
                    print "".join(list3)
                else:
                    print i                                 
        
    def main():
        str = "abcdefgabc"
        bool =  str.isdigit()
        longestSubstring(str,bool)
    if __name__ == '__main__':
        main()
     
  • keshav

    Each character need to refer its subsequent character for longest sub-string till that character. In case current character has been found already then we need to check if its most previous index lies outside the range of sub-string length of subsequent character.

     
    /* #include<stdio.h>
    #include<conio.h>
    #include<string.h>
    
    int main()
    {
        char str[100];
        int n,i,*ref,hash[256],max,Index;
        printf("enter the string\n");
        gets(str);
        n=strlen(str);
        ref= (int *)(malloc(n*(sizeof(int))));
        for(i=0;i<n;i++)
        hash[str[i]]=-1;
        hash[str[n-1]]=n-1;
        ref[n-1]=1;
        max=1;
        Index=n-1;
        for(i=n-2;i>=0;i--)
        {
            if(hash[str[i]]==-1||hash[str[i]]>(i+ref[i+1]))
            ref[i]=ref[i+1]+1;
            else
            ref[i]=hash[str[i]]-i;
            hash[str[i]]=i;
            if(ref[i]>max)
            {
                max=ref[i];
                Index=i;
            }
        }
        printf("\nLongest substring without repetitions is:"); 
        for(i=Index;i<(Index+max);i++)
        printf("%c",str[i]);
        getch();
        return 1;  
    }
     */
     
  • Code1101
     
        public int largestUniqueString(String s) {
            Set<Character> set = new HashSet<Character>();
            int[] w = new int[s.length()];
            for(int i=0; i<s.length(); i++) {
                if(set.contains(s.charAt(i))) set.clear();
    
                set.add(s.charAt(i));
                    w[i] = set.size();
            }
    
            int max=-1;
            for(int i=0; i<w.length; i++) {
                if(w[i] > max) {
                    max = w[i];
                }
            }
            return max;
        }
     
  • rahul.titare
     
    int start=0,stop=0,longestStart=0,longestStop = 0;		
    				
    		int[] counts = new int[65];
    		
    		int lastCheckedPosition = -1;
    		
    		String a = "GEEKSFORGEEKS".toUpperCase();
    		counts[a.charAt(0) - 65] = 1;
    		
    		for(int i=1;i < a.length();i++){
    			
    			if(counts[a.charAt(i)%65] == 0){		
    				
    				stop = i;
    				
    				counts[a.charAt(i)%65] = i+1;
    				
    			}else{						
    				
    				int pos = counts[a.charAt(i)%65];
    				
    				if(lastCheckedPosition < pos){					
    					
    					if(stop-start > longestStop-longestStart){
    						longestStop = stop;
    						longestStart = start;
    					}
    				
    					start = pos;					
    					stop = i;					
    					lastCheckedPosition = start;					
    				}
    
    				counts[a.charAt(i)%65] = i+1;
    				
    			}
    			
    		}
    		
    		if(stop-start > longestStop-longestStart){
    			longestStop = stop;
    			longestStart = start;
    		}
    		
    		System.out.println("Logest substring is : "+a.substring(longestStart, longestStop+1));
     
  • instead of

     
    cur_len = i - prev_index;
     

    the following would also work.

     
    cur_len--;
     
  • Arun

    Java implementation for the same::

    public static String findSubsString(String str){

    HashSet set = new HashSet();

    int max_curr = 0;
    int max_overAll = 0;
    int head = 0;
    int tail = 0;
    String longestSubstring = “”;

    while(tail < str.length()){

    if(!set.contains(str.charAt(tail))){
    max_curr++;
    set.add(str.charAt(tail));
    }else{
    int i = 0;
    for(Character c : set){
    i++;
    if(c == str.charAt(tail)){
    break;
    }
    }

    for(int j = head ; j max_overAll){
    longestSubstring = str.substring(head, tail);
    max_overAll = max_curr;
    }
    head = ++i;
    }
    tail++;
    }
    return longestSubstring;
    }

  • time pass

    the solution ( linear time ) gives output as 1 even in case of empty strings .. i think a check should be added at the begining of the function for n .. in case n is 0 , return 0

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
  • Saurabh Jain

    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Scanner;
    import java.util.Set;

    /**
    *
    * @author saurabh
    */
    public class LongestSubstringWithoutRepeatingChars
    {
    String s;

    public LongestSubstringWithoutRepeatingChars()
    {
    Scanner sc = new Scanner(System.in);
    s = sc.nextLine();
    System.out.println("\nLength of longest substring without repeating chars is : "+printLengthOfLongestNonRepeatingSubstring2());
    }

    private int printLengthOfLongestNonRepeatingSubstring2()
    {
    int start=0,len=1;
    Set<Integer> subIndex = new HashSet<Integer>();
    int[] v = new int[256];

    for(int i=0; i<256; i++)
    v[i]=-1;

    for(int i=0; i<s.length() && start<s.length(); i++)
    {
    if(v[s.charAt(i)]<start)
    {
    v[s.charAt(i)]=i;
    }
    else
    {
    start=v[s.charAt(i)]+1;
    v[s.charAt(i)]=i;
    }

    if(i-start+1>len)
    {
    len = i-start+1;
    subIndex.clear();
    subIndex.add(start);
    }
    else if(i-start+1==len)
    {
    subIndex.add(start);
    }
    }

    System.out.print("Longest Substrings without repeating characters is : ");
    Iterator<Integer> it = subIndex.iterator();
    while(it.hasNext())
    {
    int l = it.next();
    System.out.println();
    for(int i=l; i<l+len; i++)
    System.out.print(s.charAt(i));
    }

    return len;
    }

    public static void main(String[] args)
    {
    LongestSubstringWithoutRepeatingChars lswrc = new LongestSubstringWithoutRepeatingChars();
    }
    }

    This program prints all longest substrings without repeating characters. Time Complexity O(n+d), Space Complexity O(d). Correct me, if anything is wrong.

  • anubhav gupta

    #include <iostream>
    #include <map>
    #include <set>
    #include <algorithm>
    using namespace std;

    void compute(char *str,int *mins , int *maxs)
    {
    int begin,end,count=0,maxcount=-1;
    map<char,int> hash;
    hash.clear();

    for(begin = 0,end = 0 ;end < strlen(str); end++){

    hash[str[end]]++;

    if(hash[str[end]]>1){

    while(hash[str[end]]>1)
    {
    hash[str[begin]]–;

    begin ++ ;
    }
    }
    count = end-begin+1;
    if(count > maxcount)
    {
    maxcount = count;
    *maxs = end;
    *mins = begin;
    }
    }
    }

    int main()
    {

    char *str = "THISISASTRING";
    int mins,maxs;
    compute(str,&mins,&maxs);
    for(int i= mins;i <= maxs ;i++)
    printf("%c",str[i]);
    printf("\n");
    system("pause");
    }

  • Raghav

    A simple code as below would work for the O(n) solution

     
    int retMaxLenSubString(char str[]){
         if(str == null || str.length==0)
                 return 0;
         int charIndex[] = new int[256];
         for(int i=0;i<256;i++) {
           charIndex[i] = -1;
         }
    
         int maxLenStIndex = 0;
         int maxLen = 0;
    
         for(int i=0;i<str.length;i++) {
              int asciiValue = (int)str[i];
              if(index[asciiValue]>maxLenStIndex) {
                  maxLenStIndex = index[asciiValue] + 1;
              }
              index[charIndex] = i;
              maxLen = max(maxLen, i-maxLenStIndex;
          }
    }      
     
  • kartikaditya

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

    using namespace std;

    void getLongestSubstringWithoutRepeatingChars(char* s) {
    int n = strlen(s);
    int lo = 0, hi = 0, t_lo = 0, t_hi = 0, max = 0, curr = 0;
    int ht[256];
    memset(ht, -1, 256 * sizeof(int));

    for (int i = 0; i < n; ++i) {
    if (ht[s[i]] != -1) {
    for (; lo <= ht[s[i]]; ++lo) {
    ht[s[lo]] = -1;
    –curr;
    }
    }
    ht[s[i]] = i;
    ++curr;
    t_hi = i;
    if (max < curr) {
    max = curr;
    lo = t_lo;
    hi = t_hi;
    }
    }
    cout << max << endl;
    }

    int main() {
    char* s = new char[64];
    strcpy(s, "geeksforgeeks");
    getLongestSubstringWithoutRepeatingChars(s);
    strcpy(s, "ABDEFGABEF");
    getLongestSubstringWithoutRepeatingChars(s);
    strcpy(s, "BBACDBV");
    getLongestSubstringWithoutRepeatingChars(s);
    strcpy(s, "AAA");
    getLongestSubstringWithoutRepeatingChars(s);
    return 0;
    }

  • kartikaditya
     
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    
    using namespace std;
    
    int getLongestSubstringWithUniqueChars(const char* s) {
        int n = strlen(s);
        bool ht[256];
        memset(ht, false, 256 * sizeof(bool));
        int max = -1, curr = 0;
        for (int i = 0; i < n; ++i) {
            if (ht[s[i]]) {
                curr = 0;
                memset(ht, false, 256 * sizeof(bool));
            }
            ++curr;
            ht[s[i]] = true;
            if (max < curr) {
                max = curr;
            }
        }
        return max;
    }
    
    int main() {
        cout << getLongestSubstringWithUniqueChars("ABDEFGABEF") << endl;
        return 0;
    }
     
  • Rushi Agrawal

    Check the python code for the same. Looks quite elegant to me.

    from string import ascii_lowercase

    def maxss(s):
    s = list(s)
    maxlen = 0
    maxsofar = 0
    lastinstance = {}
    for i in ascii_lowercase:
    lastinstance[i] = -1
    for i in range(len(s)):
    if lastinstance[s[i]] < i – maxsofar:
    lastinstance[s[i]] = i
    maxsofar += 1
    else:
    maxsofar = i – lastinstance[s[i]]
    lastinstance[s[i]] = i
    if maxsofar > maxlen:
    maxlen = maxsofar
    return maxlen

    • Rushi Agrawal

      Correction in the above code: The line s = list(s) can and must be removed.

      lastinstance is the dictionary to keep track of the last instance of the characters. Current implementation only works with smallcase alphabets, although can be scaled easily to larger character set.

  • vikram.kuruguntla

    Program to print the one of maximum sub string which has unique chars. Characters are case sensitive.

    Please correct me, if anything is wrong.

     
    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    #define NUM_CHARS 256
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	char *input_string = "ABCabc";
    	int input_length = strlen(input_string);
    	char first_char_of_current_string = 0;
    
    	char visited[NUM_CHARS];
    	memset(visited, 0, sizeof(char) * NUM_CHARS);
    
    	int current_start_ix = 0, final_start_ix = -1, final_end_ix = -1;
    	int current_length=0;
    	int final_length=0;
    	for( int i = 0; i < input_length; i++)
    	{
    		if(visited[ input_string[i] ] == 0)
    		{
    			visited[ input_string[i] ] = 1;
    			current_length++;
    		}else if( current_length > final_length){
    
    			final_start_ix = current_start_ix;
    			final_end_ix = i - 1;
    			final_length = current_length;
    
    			if(first_char_of_current_string && visited[first_char_of_current_string ] == 0)
    			{
    				final_start_ix--;
    				final_length++;
    			}
    			
    
    			current_length = 0;
    			memset(visited, 0, sizeof(char) * NUM_CHARS);
    			first_char_of_current_string = input_string[i];		
    			current_start_ix = i + 1;
    		}
    	}
    
    	if( current_length > final_length)
    	{
    		final_start_ix = current_start_ix;
    		final_end_ix	= input_length;
    		if(first_char_of_current_string && visited[first_char_of_current_string] == 0)
    		{
    			final_start_ix--;
    			final_length++;
    		}
    	}
    	
    	for( int i = final_start_ix; i <= final_end_ix; i++)
    		cout << input_string[i];
    	cout << endl;
    
    	return 0;
    }
    
     
    • program is wronge

  • randy

    char str[] = “ABCDECQWERTYU”;

    The program does not work.

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
    • GeeksforGeeks

      @randy: The program given in the post return 8 for “ABCDECQWERTYU” which seems to be correct. CQWERTYU is the longest string without repeating characters.

      • randy

        Yes It is correct, sorry for my mistake.

         
        /* Paste your code here (You may delete these lines if not writing code) */
         
  • itengineer
     
    package com.sun.java.longestsubstring;
    
    
    public class LongestSubstring 
    {
    	private int visitedStartIndex = 0;
    	private int previousIndex = 0;
    	
    	
    	public static void main(String[] args)
    	{
    		LongestSubstring lsObject = new LongestSubstring();
    		System.out.println("length = " + lsObject.findNRCSLength("uniquesubstring"));
    	}
    		
    	/**
    	 * @return  Non Repeating Character Substring length
    	 */
    	
    	public int findNRCSLength(String string)
    	{										
    		int maxLength = -1;
    		int currentLength = 1;
    		char stringChars[] = (string.toLowerCase()).toCharArray(); 
    		
    		for(int currentIndex = 1; currentIndex < stringChars.length; currentIndex++)
    		{				
    			
    			if(!isCharVisited(currentIndex, stringChars))
    			{				
    				currentLength++;				
    			}
    			else
    			{
    				maxLength = currentLength > maxLength ? currentLength : maxLength;
    				currentLength = 1;
    				visitedStartIndex = currentIndex;										
    			}
    			
    			previousIndex = currentIndex;
    		}
    		
    		maxLength = currentLength > maxLength ? currentLength : maxLength;
    		
    		return maxLength;
    	}
    	
    	
    	private boolean isCharVisited(int index, char[] str)
    	{		
    		for(int i = visitedStartIndex; i <= previousIndex; i++)
    		{
    			if(str[index] == str[i])
    			{				
    				return true;
    			}
    		}
    
    		return false;	
    	}
    }
     

    output
    length = 8

    • itengineer

      Hey Geeks,

      Forgot to mention that the code above uses JAVA language.

  • vkjk89

    Here is one more code.
    Venki/Kartik,
    Plz suggest if anything wrong.

     
    #include<stdio.h>
    #include<conio.h>
    #include<string.h>
    int longest(char * str ,int *pos)
    {
    int len;
    int i,cur,max,*vis;
    vis=(int*)malloc(sizeof(int)*256);
    for(i=0;i<256;i++)
    vis[i]=-1;
    cur=max=0;
    len=strlen(str);
    for(i=0;i<len;i++)
    {
    if(vis[str[i]]==-1||i-cur>vis[str[i]])
    {
    vis[str[i]]=i;
    cur++;
    }
    else if(cur>max)
    	{
    	 *pos=i;
    	 max=cur;
    	 cur=1;
    	 vis[str[i]]=i;
    	}
         else cur=1;
    }
    free(vis);
    *pos=(*pos)-max;
    return max;
    
    }
    
    int main()
    {
    char *str="geeksforgeeks";
    char *sub;
    int lo;
    int pos;
    clrscr();
    lo=longest(str,&pos);
    strcpy(sub,str+pos);
    sub[lo]='\0';
    printf("substring=%s",sub);
    getch();
    return 0;
    }
    
    
    
     
  • AKKICOOL

    Can you please give a case for

    “when we are changing the NRCS, we should also check whether length of the previous NRCS was greater than max_len or not” in else part

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
  • Arpit Gupta

    In this article complexity of brute force algorithm is written as exponential but it should be O(n^3) because there will be n*(n+1)/2 substrings and considering each of atmost length n the complexity should be O(n^3).Please let me know how can it be exponential.

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
    • GeeksforGeeks

      @Arpit Gupta: Thanks for pointing this out. We have updated the post with time complexity as O(n^3).

  • camster

    Here is a recursive function that finds and prints the length of the longest substring in O(N) time complexity, O(N) space.

     
    void lcs(char arr5[], int n, int curr, 
             int&  maxlength,std::string& sofar){
    	if (n == 0){
    		return; 
    	}
    	if (arr5[0] == arr5[1]){
    		if (curr >= maxlength){
    			if (n < sofar.length()){
    				maxlength = sofar.length();
    				return;
    			}
    			sofar.clear();
    		}
    		maxlength = MAX(maxlength,curr);
    		lcs(arr5 + 1, n - 1, curr + 1, 
    		                maxlength,sofar);
    	}
    	else if (arr5[0] != arr5[1]){
    		sofar.push_back(arr5[0]);
                    maxlength = sofar.length();
    		lcs(arr5 + 1, n - 1,  
                        curr + 1, maxlength,sofar);
    	}
    }
    
    // testing
    
     char cameron[] =  {'g','e','e','k','s','f','o','r','g','e','e','k','s'}; 
      int maxlength(0);
      std::string resultstring;
    
      lcs(cameron, sizeof(cameron), 0, maxlength,resultstring);
    
      printf("maxlength = %d resultstring = %s\n",
    	    maxlength, resultstring.c_str());
    
    
    /* Paste your code here (You may delete these lines if not writing code) */
     
  • PsychoCoder
     
    #include<stdio.h>
    #include<string.h>
    
    int main() {
      char arr[26] , str[40] ;
      int i , len, index ;
      int start, maxlen = 1 , end = 0 ;
      printf ( "\nEnter the string :\t " ) ;
      scanf( "%s", str ) ;
      len = strlen (str) ;
      start = 0 ;
    
      for ( i = 0 ; i < 26 ; i ++ )
        arr[i] = -1 ;
      arr[str[0]-'a'] = 0 ;
    
      for ( i = 1 ; i < len ; i ++ ) {
        index = str[i] - 'a' ;
        if ( arr[index] >= start ) {
          if ( (i - start) > maxlen ) {
            maxlen = i-start ;
            end = i - 1;
          }
          start = arr[index] + 1 ;
        }
        arr[index] = i ;
      }
      if ( (i-start) > maxlen ) {
        maxlen = i-start ;
        end = i - 1 ;
      }
      printf ( "\nMax length is : \t%d", maxlen ) ;
      printf ( "\nIndex (start : %d - end : %d)", end-maxlen+1, end) ;
      return 0;
    }
     
    • suresh
       
      /* Paste your code here (You may delete these lines if not writing code) */
       

      for “geeksforgeeks” it print 7

  • You can reduce the space further by storing indexes instead of the array itself. Below is a solution in Java that also prints the substring.

    public class LONGESTSTRING {
    public static void main(String[] args) {
    String str = "GEEKSFORGEEKS";
    System.out.println("The input string is " + str);
    int len = longestUniqueSubsttr(str);
    System.out
    .println("The length of the longest non-repeating character substring is "
    + len);
    }

    private static int longestUniqueSubsttr(String str) {
    if (str.length() == 1)
    return 1;
    short back_ptr = 0, front_ptr = 1, max_len = -1, cur_len = 1;
    short max_back_ptr = -1, max_front_ptr = -1;
    for (short i = 1; i < str.length(); i++) {
    if (!characterExits(str, front_ptr, back_ptr, i)) {
    cur_len++;
    front_ptr++;
    } else {
    if (max_len < cur_len) {
    max_len = cur_len;
    max_back_ptr = back_ptr;
    max_front_ptr = front_ptr;
    }
    cur_len = 1;
    back_ptr = i;
    front_ptr = (short) (i + 1);
    }
    }

    if (max_len == -1) {
    max_len = cur_len;
    max_back_ptr = back_ptr;
    max_front_ptr = front_ptr;
    }
    printLSNC(str, max_back_ptr, max_front_ptr);
    return max_len;
    }

    private static void printLSNC(String str, short back_ptr, short front_ptr) {
    if (str.length() <= back_ptr || str.length() < front_ptr)
    return;
    for (int i = back_ptr; i < front_ptr; i++) {
    System.out.print(str.charAt(i));
    }
    System.out.println();
    }

    private static boolean characterExits(String str, short front_ptr,
    short back_ptr, short cur) {
    if (str.length() <= back_ptr || str.length() < front_ptr)
    return false;
    if (cur < 0 || cur > str.length())
    return false;
    for (int i = back_ptr; i < front_ptr; i++) {
    if (str.charAt(i) == str.charAt(cur))
    return true;
    }
    return false;
    }
    }

    /**
    * Output
    The input string is GEEKSFORGEEKS
    EKSFORG
    The length of the longest non-repeating character substring is 7
    */

  • Rahul
     
    int uniquesubstrlength (const char *str)
    {
      int curlen = 1, maxlen = 0;
      int n = strlen (str);
      int *visited = (int *) calloc (256, sizeof (int));
      int tag = 1;
      visited [str[0]] = tag;
    
      for (int i = 0; i < n; i++)
      {
        if (visited[str[i]] == tag)
        {
          if (curlen > maxlen)
          {
            maxlen = curlen;
          }
          curlen = 1;
          visited[str[i]] = ++tag;
        }
        else
        {
          visited[str[i]] = tag;
          curlen++;
        }
      }
      if (curlen > maxlen)
        maxlen = curlen;
      free (visited);
      return maxlen;
    }
    
     
  • camster
     
    /* Paste your code here (You may delete these lines if not writing code) */
     
    • camster

      A hashtable , STL map givea the same result. Also, I was wondering if the Knuth Pratt Moore string matching code , which has a worst cas running time of O(N) could be used to help solve this problem. Thank you for your excellent algorithm.

       
      /* Paste your code here (You may delete these lines if not writing code) */
      int longestUniqueSubsttr(char *str) {     
      	int n = strlen(str);     
      	int cur_len = 1;  // To store the lenght 
      	int max_len = 1;  // To store the result     
      	int prev_index;  // To store the previous inde
      	int i;     
      	std::map<char,int> visited;
      
      	visited[str[0]] = 1;
      	for (i = 1; i < n; i++)   {         
                    prev_index =  visited[str[i]];           
      	      if (prev_index == 0 || 
                        i - cur_len > prev_index)             
      		    cur_len++;          
      		else{             
      		if (cur_len > max_len)                 
      		    max_len = cur_len;               
      		    cur_len = i - prev_index;         
      		}           
      		visited[str[i]] = i;     
      	}       
      
      	if (cur_len > max_len)         
      		max_len = cur_len;        
      	return max_len; 
      } 
      
       
      • camster

        It is possible to find and print the longest substring without repeating characters in 0(n + d) running time. Thank you,

        int PrintLongestUniqueSubsttr(char *str) {
        int n = strlen(str);
        int cur_len = 1;
        int max_len = 1;
        int prev_index;
        int i;
        int lastn(0);
        std::map visited;

        visited[str[0]] = 1;
        for (i = 1; i prev_index) {
        cur_len++;
        if (prev_index == 0){
        lastn = i;
        }
        }
        else {
        if (cur_len > max_len){

        max_len = cur_len;
        }
        cur_len = i – prev_index;
        }
        visited[str[i]] = i;
        }
        if (cur_len > max_len)
        max_len = cur_len;
        char* answer = new char[max_len + 1];
        int ii(0);
        for (int m = lastn – max_len +1;
        m <= lastn + 1 ; m++){ answer[ii++] = str[m]; } answer[ii – 1] = ‘\x0′; printf(“answer = %s\n”,answer); delete [] answer; return max_len; }

  • mystry

    Point out if something is wrong.
    // works for lower case letters but can easily be tweaked for upper case also.

     
    // Longest Common Substring without Repeatition
    #include<stdio.h>
    int main(){
    //	char Input[]="bbbb";
    //	char Input[]="abdefgabef";
    	char Input[]="geeksforgeeks";
    	int Array[26];
    	int start_index=0,curr_len=0,max_len=0;
    	int i;
    	for(i=0;i<26;i++)
    		Array[i]=-1;
    	for(i=0;i<sizeof(Input);i++){
    		if(Array[(int)(Input[i])-97]==-1){
    			Array[(int)(Input[i])-97]=i;
    			curr_len++;
    		}
    		else{
    			if(Array[(int)(Input[i])-97]==i-curr_len){
    				Array[(int)(Input[i])-97]=i;
    //				start_index++;
    			}
    			else{
    				if(curr_len>max_len){
    					max_len=curr_len;
    					start_index=i-curr_len;
    					curr_len=i-Array[(int)(Input[i])-97]-1;
    				}
    			}
    		}
    	}
    	printf("\nMax_len\t%d\n",max_len);
    }
     

    This is O(n) time
    and O(1) space // int array of 26.

  • chakri

    The above program does not work for the below input of characters.
    char str[] = “BBACDBV”;

    • kartik

      @Chakri: The program works perfectly fine for your string, it returns 5 as “ACDBV” is the maximum length substring with unique characters.