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
#include<stdlib.h>
#include<stdio.h>
#define NO_OF_CHARS 256
int min(int a, int b);
int longestUniqueSubsttr(char *str)
{
int n = strlen(str);
int cur_len = 1; // To store the lenght of current substring
int max_len = 1; // To store the result
int prev_index; // To store the 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;
}
visited[str[i]] = i; // update the index of current character
}
// 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);
getchar();
return 0;
}
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.



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; }EXPECTING ONLY LOWER CASE ENGLISH ALPHABETS
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;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;
}
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; }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.
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()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; } */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; }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
the following would also work.
Also initialise curr_len to '0'
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;
}
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
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.
#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");
}
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; } }#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;
}
#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; }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 maxlenCorrection in the above code: The line
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.
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
char str[] = "ABCDECQWERTYU";
The program does not work.
@randy: The program given in the post return 8 for "ABCDECQWERTYU" which seems to be correct. CQWERTYU is the longest string without repeating characters.
Yes It is correct, sorry for my mistake.
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
Hey Geeks,
Forgot to mention that the code above uses JAVA language.
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; }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
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.
@Arpit Gupta: Thanks for pointing this out. We have updated the post with time complexity as O(n^3).
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) */#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; }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 */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; }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; }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;
}
http://effprog.blogspot.com/2011/07/to-find-longest-substring-with-unique.html#comment-form
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.
The above program does not work for the below input of characters.
char str[] = "BBACDBV";
@Chakri: The program works perfectly fine for your string, it returns 5 as "ACDBV" is the maximum length substring with unique characters.