Given a string, find the longest substring without any repeating characters.
F longest_substring2(s) V max_subs = [s[0.<1]] * 0 V mx = 0 L(x) 0 .< s.len L(y) x + 1 .. s.len V sub = s[x .< y] I y - x >= mx & sub.len == Set(Array(sub)).len I y - x == mx & sub !C max_subs max_subs.append(sub) E max_subs = [sub] mx = y - x R max_subsL(s) [‘xyzyabcybdfd’, ‘xyzyab’, ‘zzzzz’, ‘a’, ‘’] print(s‘ => ’longest_substring2(s))V arr = [1, 2, 3, 4, 1, 2, 5, 6, 1, 7, 8, 1, 0]print(arr‘ => ’longest_substring2(arr))
xyzyabcybdfd => [zyabc, cybdf]xyzyab => [zyab]zzzzz => [z]a => [a] => [][1, 2, 3, 4, 1, 2, 5, 6, 1, 7, 8, 1, 0] => [[3, 4, 1, 2, 5, 6], [2, 5, 6, 1, 7, 8]]
BYTE FUNC GetLength(CHAR ARRAY s BYTE start) BYTE ARRAY tab(256) BYTE i CHAR c Zero(tab,256) i=start WHILE i<=s(0) DO c=s(i) tab(c)==+1 IF tab(c)>1 THEN EXIT FI i==+1 ODRETURN (i-start)PROC LongestSubstrings(CHAR ARRAY s) CHAR ARRAY tmp(256) BYTE count,maxLen,i,len IF s(0)=0 THEN RETURN FI i=1 maxLen=0 FOR i=1 TO s(0) DO len=GetLength(s,i) IF len>maxLen THEN maxLen=len FI OD count=0 FOR i=1 TO s(0) DO len=GetLength(s,i) IF len=maxLen THEN IF count>0 THEN Print(", ") FI SCopyS(tmp,s,i,i+maxlen-1) PrintF("""%S""",tmp) count==+1 FI ODRETURNPROC Test(CHAR ARRAY s) PrintF("Input: ""%S""%E",s) Print("Result: [") LongestSubstrings(s) PrintE("]") PutE()RETURNPROC Main() Test("xyzyabcybdfd") Test("xyzyab") Test("zzzzz") Test("a") Test("thisisastringtest") Test("")RETURN
Screenshot from Atari 8-bit computer
Input: "xyzyabcybdfd"Result: ["zyabc", "cybdf"]Input: "xyzyab"Result: ["zyab"]Input: "zzzzz"Result: ["z", "z", "z", "z", "z"]Input: "a"Result: ["a"]Input: "thisisastringtest"Result: ["astring", "ringtes"]Input: ""Result: []
withAda.Text_IO;procedureLongest_SubstringisfunctionLongest(Item:String)returnStringisHist:array(Character)ofNatural:=(others=>0);First:Natural:=Item'First;Last:Natural:=Item'First-1;Longest_First:Natural:=Item'First;Longest_Last:Natural:=Item'First-1;procedureAdjustisbeginifLast-First>Longest_Last-Longest_FirstthenLongest_First:=First;Longest_Last:=Last;endif;endAdjust;beginifItem=""thenreturnItem;endif;forIndexinItem'RangeloopLast:=Index;Hist(Item(Index)):=Hist(Item(Index))+1;ifHist(Item(Index))=1thenAdjust;elseforAinFirst..Indexloopif(forallEofHist=>E<=1)thenFirst:=A;Adjust;exit;endif;Hist(Item(A)):=Hist(Item(A))-1;endloop;endif;endloop;returnItem(Longest_First..Longest_Last);endLongest;procedureTest(Item:String)isuseAda.Text_IO;beginPut("original : '");Put(Item);Put_Line("'");Put("longest : '");Put(Longest(Item));Put_Line("'");endTest;beginTest("");Test("a");Test("xyzyabcybdfd");Test("thisisastringtest");Test("zzzzz");endLongest_Substring;
original : ''longest : ''original : 'a'longest : 'a'original : 'xyzyabcybdfd'longest : 'zyabc'original : 'thisisastringtest'longest : 'astring'original : 'zzzzz'longest : 'z'
lswrc←{sfx←⌽∘,¨,\∘⌽wrc←⊢(/⍨)⍳∘⍴(∧\=)⍳⍨ls←⊢(/⍨)(⌈/=⊢)∘(≢¨)lswrc¨sfx⍵}
lswrc¨ 'xyzyabcybdfd' 'xyzyab' 'zzzzz' 'a' ''┌─────────────┬──────┬───────────┬───┬┐│┌─────┬─────┐│┌────┐│┌─┬─┬─┬─┬─┐│┌─┐││││cybdf│zyabc│││zyab│││z│z│z│z│z│││a││││└─────┴─────┘│└────┘│└─┴─┴─┴─┴─┘│└─┘││└─────────────┴──────┴───────────┴───┴┘
unrepeatableSubstrings:function[s][result:[["",0]]ifzero?s->return[]ifone? s -> return @[s]loop0..decsizes'a[if(a+1)=<decsizes[loopa..decsizes'b[substr:to:stringslicesabss:sizesubstrifand?->ss>=lastmaximumresult'x->lastx->substr=uniquesubstr[result:(selectresult'x->ss=lastx)++@[@[substr,ss]]]]]]result:uniquemapresult'x->firstxreturnresult]loop["xyzyabcybdfd","xyzyab","zzzzz","a",""]'str->print[str"=> longest unrepeatable substring:"unrepeatableSubstringsstr]
xyzyabcybdfd => longest unrepeatable substring: [zyabc cybdf] xyzyab => longest unrepeatable substring: [zyab] zzzzz => longest unrepeatable substring: [z] a => longest unrepeatable substring: [a] => longest unrepeatable substring: []
LSWRC(str){found:=[],result:=[],maxL:=0if(StrLen(str)=1)result[str]:=trueelsewhile(StrLen(str)>=2){s:=strwhileStrLen(s)>=maxL{if!(s~="(.).*\1"){found[s]:=truemaxL:=maxL<StrLen(s)?StrLen(s):maxLbreak}s:=SubStr(s,1,StrLen(s)-1); trim last chr}str:=SubStr(str,2); trim 1st chr and try again}maxL:=0forstrinfoundmaxL:=maxL<StrLen(str)?StrLen(str):maxLforstrinfoundif(StrLen(str)=maxL)result[str]:=truereturnresult}
Examples:
db=(xyzyabcybdfdxyzyabzzza)fori,lineinStrSplit(db,"`n","`r"){result:="[",i:=0forstrinLSWRC(line)result.=str", "output.=line"`t> "Trim(result,", ")"]`n"}MsgBox%outputreturn
xyzyabcybdfd> [cybdf, zyabc]xyzyab> [zyab]zzz> [z]a> [a]
get "libhdr"// Fills up 'v' with words where w%0 is the start and w%1 is the end // of each longest substringlet lswrc(s, v) = valof$( let seen = vec 255 let start = 1 and i = 1 and maxStart = 1 and maxEnd = 1 and n = 0 for i=0 to 255 do i!seen := false while i <= s%0 $( test (s%i)!seen while (s%i)!seen $( (s%start)!seen := false start := start + 1 $) or $( (s%i)!seen := true if i - start >= maxEnd - maxStart $( maxStart := start maxEnd := i while n>0 & (v+n-1)%1 - (v+n-1)%0 < i-start do n := n-1 (v+n)%0 := start (v+n)%1 := i n := n+1 $) i := i + 1 $) $) resultis n$)let substr(s, start, end, buf) = valof$( buf%0 := end - start + 1 for i = start to end do buf%(i-start+1) := s%i resultis buf$)let example(s) be$( let v = vec 32 and b = vec 32 let n = lswrc(s, v) writef("Original string: '%s'*N", s) writes("Longest substrings: ") test n=0 do writes("<empty>") or for i = 0 to n-1 do writef("'%s' ", substr(s, (v+i)%0, (v+i)%1, b)) wrch('*N')$)let start() be$( example("xyzyabcybdfd") example("xyzyab") example("zzzzz") example("a") example("")$)
Original string: 'xyzyabcybdfd'Longest substrings: 'zyabc' 'cybdf'Original string: 'xyzyab'Longest substrings: 'zyab'Original string: 'zzzzz'Longest substrings: 'z' 'z' 'z' 'z' 'z'Original string: 'a'Longest substrings: 'a'Original string: ''Longest substrings: <empty>
LongUniq←⌈´⊸=∘(≠¨)⊸/∧`∘∊⊸/¨∘↓
Alternative:
LongUniq←⊢´∘⊔∘(≠¨)⊸⊏∊⊸⊐⟜0⊸↑¨∘↓
Test:
LongUniq¨"a"‿""‿"zzz"‿"xyzyab"‿"xyzyabcybdfd"
┌─· ⟨ "a" ⟩ ⟨ ⟨⟩ ⟩ ⟨ "z" "z" "z" ⟩ ⟨ "zyab" ⟩ ⟨ "zyabc" "cybdf" ⟩ ┘
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<stdbool.h>structsubstr{constchar*start;size_tlength;};structsubstr*lswrc(constchar*str){size_tlength=strlen(str);structsubstr*arr=malloc(sizeof(structsubstr)*(length+1));if(!arr)returnNULL;size_tstart=0,i=0,maxStart=0,maxEnd=0,n=0;boolused[256]={false};for(i=0;i<length;i++){while(used[(unsignedchar)str[i]])used[(unsignedchar)str[start++]]=false;used[(unsignedchar)str[i]]=true;if(i-start>=maxEnd-maxStart){maxStart=start;maxEnd=i;size_tlen=maxEnd-maxStart+1;while(n>0&&arr[n-1].length<len)n--;arr[n].start=&str[start];arr[n].length=len;n++;}}arr[n].start=NULL;arr[n].length=0;returnrealloc(arr,sizeof(structsubstr)*(n+1));}intmain(){char*examples[]={"xyzyabcybdfd","xyzyab","zzzzz","a","",NULL};for(size_ti=0;examples[i];i++){printf("Original string:\"%s\"\n",examples[i]);printf("Longest substrings: ");structsubstr*ls=lswrc(examples[i]);for(size_tj=0;ls[j].start;j++)printf("\"%.*s\" ",(int)ls[j].length,ls[j].start);printf("\n");free(ls);}return0;}
Original string: "xyzyabcybdfd"Longest substrings: "zyabc" "cybdf"Original string: "xyzyab"Longest substrings: "zyab"Original string: "zzzzz"Longest substrings: "z" "z" "z" "z" "z"Original string: "a"Longest substrings: "a"Original string: ""Longest substrings:
#include<iostream>#include<fstream>#include<set>#include<sstream>#include<string>#include<vector>std::vector<std::string>longest_substrings_without_repeats(conststd::string&str){size_tmax_length=0;std::vector<std::string>result;size_tlength=str.size();for(size_toffset=0;offset<length;++offset){std::set<char>characters;size_tlen=0;for(;offset+len<length;++len){if(characters.find(str[offset+len])!=characters.end())break;characters.insert(str[offset+len]);}if(len>max_length){result.clear();max_length=len;}if(len==max_length)result.push_back(str.substr(offset,max_length));}returnresult;}voidprint_strings(conststd::vector<std::string>&strings){std::cout<<"[";for(size_ti=0,n=strings.size();i<n;++i){if(i>0)std::cout<<", ";std::cout<<'\''<<strings[i]<<'\'';}std::cout<<"]";}voidtest1(){for(std::stringstr:{"xyzyabcybdfd","xyzyab","zzzzz","a","thisisastringtest",""}){std::cout<<"Input: '"<<str<<"'\nResult: ";print_strings(longest_substrings_without_repeats(str));std::cout<<"\n\n";}}std::stringslurp(std::istream&in){std::ostringstreamout;out<<in.rdbuf();returnout.str();}voidtest2(conststd::string&filename){std::ifstreamin(filename);if(!in){std::cerr<<"Cannot open file '"<<filename<<"'.\n";return;}std::cout<<"Longest substring with no repeats found in '"<<filename<<"': ";print_strings(longest_substrings_without_repeats(slurp(in)));std::cout<<"\n";}intmain(){test1();test2("unixdict.txt");}
Input: 'xyzyabcybdfd'Result: ['zyabc', 'cybdf']Input: 'xyzyab'Result: ['zyab']Input: 'zzzzz'Result: ['z', 'z', 'z', 'z', 'z']Input: 'a'Result: ['a']Input: 'thisisastringtest'Result: ['astring', 'ringtes']Input: ''Result: []Longest substring with no repeats found in 'unixdict.txt': ['mboweldisgrunt']
func$[] longstr s$ . subr maxtest if len sub$ >= max if len sub$ > max max = len sub$ max$[] = [ ] . max$[] &= sub$ . . s$[] = strchars s$ len empty[] 255 len pos[] 255 pos = 1 while pos <= len s$[] c = strcode s$[pos] if pos[c] > 0 maxtest pos = pos[c] + 1 pos[] = empty[] sub$ = "" c = strcode s$[pos] . pos[c] = pos sub$ &= strchar c pos += 1 . maxtest return max$[].for s$ in [ "xyzyabcybdfd" "xyzyab" "zzzzz" "a" "thisisastringtest" "" ] print longstr s$.
[ "zyabc" "cybdf" ][ "zyab" ][ "z" "z" "z" "z" "z" ][ "a" ][ "astring" "ringtes" ][ "" ]
USING:formattinggroupingiokernelmathsequencessets;:unique-substrings(seqn--newseq)tuck<clumps>[cardinality=]withfilter;:longest-unique-substring(seq--newseq)duplength{}[2dupempty?swap0>and][drop2dupunique-substrings[1-]dip]while2nip[""like]mapmembers;:test(seq--)duplongest-unique-substring"%u -> %u\n"printf;"Longest substrings without repeating characters:"print{"xyzyabcybdfd""xyzyab""zzzzz""a"""}[test]each
Longest substrings without repeating characters:"xyzyabcybdfd" -> { "zyabc" "cybdf" }"xyzyab" -> { "zyab" }"zzzzz" -> { "z" }"a" -> { "a" }"" -> { }
dimasstringexample="antidisestablishmentarianism is a long word and so is flibbertigibbet."functionnrls(tasstring)asstringdimasintegerbest=0,best_length=-100,i=1,j,k,curr_lengthdimasstringcfori=1tolen(t)+1curr_length=0forj=i+1tolen(t)+1curr_length+=1c=mid(t,j,1)fork=itoj-1ifc=mid(t,k,1)thengotonextinextknextjnexti:ifcurr_length>best_lengththenbest_length=curr_lengthbest=iendifnextireturnmid(t,best,best_length)endfunctionprint">";nrls(example);"<"print">";nrls("My spoon is too big.");"<"print">";nrls("Rosetta Code.");"<"print">";nrls("AAAAA");"<"print">";nrls("abcdefghijklmnopqrstuvwxyz");"<"print">";nrls("aaa aeiou uuu");"<"
>blishmentar<>My spo<>ta Code.<>A<>abcdefghijklmnopqrstuvwxyz<> aeiou<
local fn substrings( t as CFStringRef ) int beg, c, f, rpt, max = 0 for beg = 0 to len(t) - 1 rpt = instr( beg+1, t, mid(t, beg, 1), NSCaseInsensitiveSearch ) if rpt < 0 then rpt = len(t) c = beg + 1 while c < rpt f = instr(c + 1, t, mid(t, c, 1), NSCaseInsensitiveSearch) if f < 0 then f = len(t) else if f < rpt then rpt = f c++ wend if rpt - beg < max then continue if rpt - beg > max then max = rpt - beg : mda_clear mda_add(0) = mid(t, beg, max) next print @"\n The string: \"";t;@"\"\n Substring/s: "; for c = 0 to mda_count(0) -1 print @"\"";mda(c);@"\" "; next printend fnwindow 1, @"Longest Substring/s Without Repeated Letters"fn substrings(@"xyzyabcybdfd")fn substrings(@"thisisastringtest")fn substrings(@"My spoon is too big.")fn substrings(@"Rosetta Code")fn substrings(@"AaAaA")fn substrings(@"abcdefghijklmnopqrstuvwxyz")fn substrings(@"aaa aeiou uuu")fn substrings(@"abcdABCD")handleevents
File:Longest Substrings without Repeated Letters.png
packagemainimport"fmt"funcsubstrings(sstring)[]string{n:=len(s)ifn==0{return[]string{""}}varss[]stringfori:=0;i<n;i++{forle:=1;le<=n-i;le++{ss=append(ss,s[i:i+le])}}returnss}funcdistinctRunes(chars[]rune)[]rune{m:=make(map[rune]bool)for_,char:=rangechars{m[char]=true}varl[]runefork:=rangem{l=append(l,k)}returnl}funcdistinctStrings(strings[]string)[]string{m:=make(map[string]bool)for_,str:=rangestrings{m[str]=true}varl[]stringfork:=rangem{l=append(l,k)}returnl}funcmain(){fmt.Println("The longest substring(s) of the following without repeating characters are:\n")strs:=[]string{"xyzyabcybdfd","xyzyab","zzzzz","a",""}for_,s:=rangestrs{varlongest[]stringlongestLen:=0for_,ss:=rangesubstrings(s){iflen(distinctRunes([]rune(ss)))==len(ss){iflen(ss)>=longestLen{iflen(ss)>longestLen{longest=longest[:0]longestLen=len(ss)}longest=append(longest,ss)}}}longest=distinctStrings(longest)fmt.Printf("String = '%s'\n",s)fmt.Println(longest)fmt.Printf("Length = %d\n\n",len(longest[0]))}}
The longest substring(s) of the following without repeating characters are:String = 'xyzyabcybdfd'[zyabc cybdf]Length = 5String = 'xyzyab'[zyab]Length = 4String = 'zzzzz'[z]Length = 1String = 'a'[a]Length = 1String = ''[]Length = 0
Implementation:
longnorep=:{{c=.#ywhile.ss=.c]\ydo.cnt=.#@~."1ssif.ce.cntdo.~.ss#~c=cntreturn.end.c=.c-1end.}}
Examples:
longnorep'xyzyabcybdfd'zyabccybdflongnorep'xyzyab'zyablongnorep'zzzzz'zlongnorep''longnorep'astring'astringlongnorep'thisisastringtest'astringringteslongnorep'Thequickbrownfoxjumpsoverthelazydog'Thequickbrownf
This also works on sequences of numbers (though the character representation of the sequences of numbers may contain repeated characters, the represented numbers will not contain repetitions):
longnorep1234125617810341256256178
importjava.util.ArrayList;importjava.util.HashSet;importjava.util.List;importjava.util.Set;publicfinalclassLongestSubstringsWithoutRepeatingCharacters{publicstaticvoidmain(String[]args){System.out.println("The longest substring(s) of the following without repeating characters are:");System.out.println();List<String>tests=List.of("xyzyabcybdfd","xyzyab","zzzzz","a","");tests.forEach(test->{List<String>result=newArrayList<String>();intlongestLength=0;for(Stringsubstring:allSubstrings(test)){if(substring.length()==substring.chars().distinct().count()){if(substring.length()>=longestLength){if(substring.length()>longestLength){result.clear();longestLength=substring.length();}result.addLast(substring);}}}System.out.println("String = '"+test+"' => "+result+" with length = "+result.getFirst().length());});}privatestaticSet<String>allSubstrings(Stringtext){Set<String>result=newHashSet<String>();result.add("");for(inti=0;i<text.length();i++){for(intj=i+1;j<=text.length();j++){result.add(text.substring(i,j));}}returnresult;}}
The longest substring(s) of the following without repeating characters are:String = 'xyzyabcybdfd' => [cybdf, zyabc] with length = 5String = 'xyzyab' => [zyab] with length = 4String = 'zzzzz' => [z] with length = 1String = 'a' => [a] with length = 1String = '' => [] with length = 0
Adapted fromJulia
Works with gojq, the Go implementation of jq
# Use a dictionary for speed in case of very long stringsdef alluniquehead: length as $n | if $n <= 1 then . else . as $in | {ix: -1} | until(.i or (.ix == $n); .ix += 1 | $in[.ix:.ix+1] as $x | if .dict[$x] then .i = .ix else .dict[$x] = true end ) | $in[: .ix] end ; def maximal_substring_with_distinct_characters: . as $in | length as $n | {i: -1} | until( .i == $n or .stop; .i += 1 | if .max and .max > $n - .i then .stop = true else ($in[.i:] | alluniquehead) as $head| if ($head|length) > .max then .ans = $head | .max = ($head|length) else . endend) | .ans;
Test Cases
"xyzyabcybdfd","xyzyab","zzzzz","a", "α⊆϶α϶",""| "\"\(.)\" => \"\(maximal_substring_with_distinct_characters)\""
"xyzyabcybdfd" => "zyabc""xyzyab" => "zyab""zzzzz" => "z""a" => "a""α⊆϶α϶" => "α⊆϶""" => ""
Works on any array, treating a character string as a character array.
functionalluniquehead(arr)len=length(arr)iflen>1foriin2:lenifarr[i]in@viewarr[1:i-1]returnarr[1:i-1]endendendreturnarr[:]endfunctionmaxuniques(arr)length(arr)<2&&returnarramax=[alluniquehead(@viewarr[i:end])foriin1:length(arr)]maxlen=maximum(map(length,amax))returnfilter(a->length(a)==maxlen,amax)endforsin["xyzyabcybdfd","xyzyab","zzzzz","a","α⊆϶α϶","",[1,2,3,4,1,2,5,6,1,7,8,1,0]]uarray=maxuniques(collect(s))!isempty(uarray)&&length(uarray[1])>1&&uarray[1][1]isaChar&&(uarray=String.(uarray))println("\"$s\" => ",uarray)end
"xyzyabcybdfd" => ["zyabc", "cybdf"]"xyzyab" => ["zyab"]"zzzzz" => [['z'], ['z'], ['z'], ['z'], ['z']]"a" => ['a']"α⊆϶α϶" => ["α⊆϶", "⊆϶α"]"" => Char[]"[1, 2, 3, 4, 1, 2, 5, 6, 1, 7, 8, 1, 0]" => [[3, 4, 1, 2, 5, 6], [2, 5, 6, 1, 7, 8]]
main :: [sys_message]main = [ Stdout (show test ++ " -> " ++ show (lswrc test) ++ "\n") | test <- tests]tests :: [[char]]tests = ["xyzyabcybdfd", "xyzyab", "zzz", "a"]lswrc :: [*]->[[*]]lswrc s = nub [s' | s'<-noreps; #s' = maxlen] where maxlen = max (map (#) noreps) noreps = [norep (drop n s) | n<-[0..#s-1]] norep = reverse . norep' [] norep' mem [] = mem norep' mem (a:as) = mem, if a $in mem = norep' (a:mem) as, otherwisein :: *->[*]->boolin item [] = Falsein item (a:as) = a = item \/ item $in asnub :: [*]->[*]nub = reverse . nub' [] where nub' mem [] = mem nub' mem (a:as) = nub' mem as, if a $in mem = nub' (a:mem) as, otherwise
"xyzyabcybdfd" -> ["zyabc","cybdf"]"xyzyab" -> ["zyab"]"zzz" -> ["z"]"a" -> ["a"]
MODULELSWRC;FROMInOutIMPORTWriteString,WriteLn;FROMStringsIMPORTLength,Copy;TYPERange=RECORDstart,length:CARDINAL;END;(* Returns start and length of every longest substring *)PROCEDURElswrc(in:ARRAYOFCHAR;VARout:ARRAYOFRange):CARDINAL;VARi,num,start,strlen,len,maxStart,maxEnd:CARDINAL;used:ARRAY[0..255]OFBOOLEAN;BEGINFORi:=0TO255DOused[i]:=FALSE;END;strlen:=Length(in);start:=0;maxStart:=0;maxEnd:=0;i:=0;num:=0;WHILEi<strlenDOIFNOTused[ORD(in[i])]THENused[ORD(in[i])]:=TRUE;IF(i-start)>=(maxEnd-maxStart)THENmaxStart:=start;maxEnd:=i;len:=(maxEnd-maxStart+1);WHILE(num>0)AND(out[num-1].length<len)DODEC(num);END;out[num].start:=start;out[num].length:=len;INC(num);END;INC(i);ELSEWHILEused[ORD(in[i])]DOused[ORD(in[start])]:=FALSE;INC(start);END;END;END;RETURNnum;ENDlswrc;PROCEDUREExample(s:ARRAYOFCHAR);VARbuf:ARRAY[0..127]OFCHAR;ranges:ARRAY[0..127]OFRange;i,n:CARDINAL;BEGINWriteString("Original string: ");WriteString(s);WriteLn();n:=lswrc(s,ranges);WriteString("Longest substrings: ");IFn=0THENWriteString("<empty>");ELSEFORi:=0TOn-1DOCopy(s,ranges[i].start,ranges[i].length,buf);buf[ranges[i].length]:=CHR(0);WriteString(buf);WriteString(" ");END;END;WriteLn();ENDExample;BEGINExample("xyzyabcybdfd");Example("xyzyab");Example("zzzzz");Example("a");Example("");ENDLSWRC.
Original string: xyzyabcybdfdLongest substrings: zyabc cybdfOriginal string: xyzyabLongest substrings: zyabOriginal string: zzzzzLongest substrings: z z z z zOriginal string: aLongest substrings: aOriginal string:Longest substrings: <empty>
This version converts strings to sequences of runes.
importsequtils,strutils,unicodetypeRunes=seq[Rune]funclongestSubstrings(str:string):seq[string]=varrunes=str.toRunesvarcurrent:Runesvarres:seq[Runes]# Result as a list of Runes.varmaxlen=0forcinrunes:letidx=current.find(c)ifidx>=0:ifcurrent.len>maxlen:res=@[current]maxlen=current.lenelifcurrent.len==maxlenandcurrentnotinres:res.addcurrentcurrent.delete(0,idx)current.addc# Process the last current string.ifcurrent.len>maxlen:res=@[current]elifcurrent.len==maxlenandcurrentnotinres:res.addcurrentresult=res.mapIt($it)forstrin["xyzyabcybdfd","xyzyab","zzzzz","a","α⊆϶α϶",""]:echo'"',str,'"'," → ",longestSubstrings(str)echo"\nLongest substrings in concatenated list of words from “unixdict.txt”: ",longestSubstrings(toSeq("unixdict.txt".lines).join())
"xyzyabcybdfd" → @["zyabc", "cybdf"]"xyzyab" → @["zyab"]"zzzzz" → @["z"]"a" → @["a"]"α⊆϶α϶" → @["α⊆϶", "⊆϶α"]"" → @[""]Longest substrings in concatenated list of words from “unixdict.txt”: @["mboweldisgrunt"]
Gets the same answer that raku does when run against unixdict.txt
#!/usr/bin/perlusestrict;# Longest_substrings_without_repeating_charactersusewarnings;formy$string(qw( xyzyabcybdfd xyzyab zzzzz a thisisastringtest )){local$_=$string;my@sub;length$+>=$#suband++$sub[length$+]{$+}whiles/.*(.)(.*\K\1.*)|(.+)//s;printf"%20s -> %s\n",$string,join' ',sortkeys%{pop@sub};}
xyzyabcybdfd -> cybdf zyabc xyzyab -> zyab zzzzz -> z a -> a thisisastringtest -> astring ringtes
Single pass, maintains a start position and a table of seen character positions.
If the current character has occurred after start, move that along, then add any longer/equal length start..i to the result set.
Note that having moved start along we certainly won't be any longer than but may still beequal to maxlen.
Should be exponentially faster than collecting all possible substrings and eliminating those with duplicate characters or too short.
It will however collect duplicates (when long enough) before weeding them out at the end.
withjavascript_semanticsfunctionlongest_substrings(sequences)-- -- s can be a normal 8-bit acsii/ansi string or a -- 32-bit unicode sequence from eg utf8_to_utf32(). -- It will not complain if given utf-8, but may -- chop up multibyte characters inappropriately. -- s must not contain any 0 or non-integers. --sequenceres={},found=repeat(0,256)-- (ansi, position)integerstart=1,maxlen=0fori=1tolength(s)dointegersi=s[i]-- (deliberate typecheck)ifsi>length(found)then-- (must be unicode then)assert(si<=#10FFFF)-- (limit size to valid chars)found&=repeat(0,si-length(found))elseintegerfi=found[si]iffi>=startthenstart=fi+1endifendiffound[si]=iintegernewlen=i-start+1ifnewlen>=maxlenthenifnewlen>maxlenthenres={}maxlen=newlenendifres=append(res,s[start..i])endifendforres=unique(res,"STABLE")returnresendfunction?longest_substrings("xyzyabcybdfd")?longest_substrings("xyzyab")?longest_substrings("zzzzz")?longest_substrings("a")?longest_substrings("")
{"zyabc","cybdf"}{"zyab"}{"z"}{"a"}{}
A quick test on unixdict.txt yielded the same results as Raku.
The following algorithm works but is not terribly efficient for long strings.
deflongest_substring(s="xyzyab"):substr=[s[x:y]forxinrange(len(s))foryinrange(x+1,len(s)+1)]no_reps=[]forsubinsubstr:iflen(sub)==len(set(sub))andsubnotinno_reps:no_reps.append(sub)max_len=max(len(sub)forsubinno_reps)ifno_repselse0max_subs=[subforsubinno_repsiflen(sub)==max_len]returnmax_subsif__name__=='__main__':forsin["xyzyabcybdfd","xyzyab","zzzzz","a","α⊆϶α϶","",[1,2,3,4,1,2,5,6,1,7,8,1,0]]:print(f"{s} =>{longest_substring(s)}")
xyzyabcybdfd => ['zyabc', 'cybdf']xyzyab => ['zyab']zzzzz => ['z']a => ['a']α⊆϶α϶ => ['α⊆϶', '⊆϶α'] => [][1, 2, 3, 4, 1, 2, 5, 6, 1, 7, 8, 1, 0] => [[3, 4, 1, 2, 5, 6], [2, 5, 6, 1, 7, 8]]
The following algorithm only accrues the longest so far.
deflongest_substring2(s="xyzyab"):max_subs,mx=[],0forxinrange(len(s)):foryinrange(x+1,len(s)+1):sub=s[x:y]ify-x>=mxandlen(sub)==len(set(sub)):ify-x==mxandsubnotinmax_subs:max_subs.append(sub)else:max_subs,mx=[sub],y-xreturnmax_subs
It gives the same output as functionlongest_substring()
above.
Detectsany character when checking for repeated characters, even multi-byte composite characters, control sequences and whitespace.
Note that there is no requirement that the substrings be unique, only that each has no repeated characters internally.
Not going to bother handling arrays since an array is not a string, and the task descriptionspecifically says 'Given a string'.
subabbreviate ($_) { .chars >80 ??"(abbreviated)\n" ~ .substr(0,35) ~' ... ' ~ .substr(*-35) !!$_ }sublongest ($string) {return0 => []unless$string.chars;my ($start,$end,@substr) =0,0;while ++$end <$string.chars {my$sub =$string.substr($start,$end -$start);if$sub.contains:my$next =$string.substr:$end,1 {@substr[$end -$start].push($sub)if$end -$start >=@substr.end;$start +=1 +$sub.index($next); } }@substr[$end -$start].push:$string.substr($start);@substr.pairs.tail}# Testingsay"\nOriginal string: {abbreviate $_}\nLongest substring(s) chars: ", .&longest# Standard testsforflatqww<xyzyabcybdfdxyzyabzzzzza'' >,# multibyte Unicode< 👒🎩🎓👩👩👦👦🧢🎓👨👧👧👒👩👩👦👦🎩🎓👒🧢α⊆϶α϶ >,# check a fileslurp'unixdict.txt';
Original string: xyzyabcybdfdLongest substring(s) chars: 5 => [zyabc cybdf]Original string: xyzyabLongest substring(s) chars: 4 => [zyab]Original string: zzzzzLongest substring(s) chars: 1 => [z z z z z]Original string: aLongest substring(s) chars: 1 => [a]Original string: Longest substring(s) chars: 0 => []Original string: 👒🎩🎓👩👩👦👦🧢🎓👨👧👧👒👩👩👦👦🎩🎓👒🧢Longest substring(s) chars: 6 => [🧢🎓👨👧👧👒👩👩👦👦🎩]Original string: α⊆϶α϶Longest substring(s) chars: 3 => [α⊆϶ ⊆϶α]Original string: (abbreviated)10th1st2nd3rd4th5th6th7th8t ... rianzoundszucchinizurichzygoteLongest substring(s) chars: 15 => [mboweldisgrunt]
/*REXX pgm finds the longest substring (in a given string) without a repeating character*/parsearg$/*obtain optional argument from the CL.*/if$==''|$==","then$='xyzyabcybdfd'/*Not specified? Then use the default.*/L=length($)/*L: the length of the given string.*/maxL=0/*MAXL: max length substring (so far).*/@.=/*array to hold the max len substrings.*/doj=1forL;b=substr($,j,1)/*search for max length substrings. */x=/*X: the substring, less the 1st char*/dok=j+1toL;x=x||substr($,k,1)/*search for the max length substrings.*/if\OKx(x)theniteratej/*Are there an replications? Skip it. */_=length(x);if_<maxLtheniterate/*is length less then the current max? */@._=@._x;maxL=_/*add this substring to the max list. */end/*k*/end/*j*/say'longest substring's(words(@.maxL))"in "$' ───► '@.maxLexit0/*stick a fork in it, we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/s:ifarg(1)==1thenreturnarg(3);returnword(arg(2)'s',1)/*simple pluralizer*//*──────────────────────────────────────────────────────────────────────────────────────*/OKx:procedure;parseargy;dor=1forlength(y)-1/*look for duplicate chars.*/ifpos(substr(y,r,1),y,r+1)>0thenreturn0end/*r*/;return1
longest substrings in xyzyabcybdfd ───► zyabc cybdf
see "working..." + nlsee "Longest substrings without repeating characters are:" + nlstr = "xyzyabcybdfd"see "Input: " + str + nllenStr = len(str)strOk = []lenOk = 0for n = 1 to lenStr for m = 1 to lenStr-n+1 temp = substr(str,n,m) add(strOk,temp) nextnextfor n = len(strOk) to 1 step -1 if len(strOK[n]) = 1 del(strOK,n) oknextfor n = 1 to len(strOK) for m = 1 to len(strOK)-1 if len(strOK[m+1]) > len(strOK[m]) temp = strOK[m] strOK[m] = strOK[m+1] strOK[m+1] = temp ok nextnextfor n = 1 to len(strOK) flag = 1 for m = 1 to len(strOK[n]) for p = m+1 to len(strOK[n]) if strOK[n][m] = strOK[n][p] flag = 0 exit ok next next if flag = 1 if len(strOK[n]) >= lenOk see "len = " + len(strOK[n]) + " : " + strOK[n] + nl lenOK = len(strOK[n]) ok oknextsee "done..." + nl
working...Longest substrings without repeating characters are:Input: xyzyabcybdfdlen = 5 : zyabclen = 5 : cybdfdone...
useitertools::Itertools;usestd::fs;fnnonrepeating(s:&str)->Vec<String>{letmutmax_subs:Vec<String>=vec![];letmutmx=0_usize;foriin0..s.len(){forjini+1..=s.len(){letsub=&s[i..j];letsubbytes=sub.chars().sorted().dedup();ifj-i>=mx&&sub.len()==subbytes.collect_vec().len(){ifj-i==mx&&!max_subs.contains(&sub.to_string()){max_subs.push(sub.to_string());}else{max_subs=vec![sub.to_string()];mx=j-i;}}}}returnmax_subs;}fnmain(){letwordsfile=fs::read_to_string("unixdict.txt").unwrap().to_lowercase();letresults=wordsfile.split_whitespace().map(|w|format!("{} ==> {:?}",w,nonrepeating(w)));forsinresults{println!("{}",s);}}
10th ==> ["10th"]1st ==> ["1st"]2nd ==> ["2nd"]3rd ==> ["3rd"]4th ==> ["4th"]5th ==> ["5th"]6th ==> ["6th"]7th ==> ["7th"]8th ==> ["8th"]9th ==> ["9th"]a ==> ["a"]a&m ==> ["a&m"]a&p ==> ["a&p"]a's ==> ["a's"]aaa ==> ["a"]aaas ==> ["as"]aarhus ==> ["arhus"]aaron ==> ["aron"] ... many lines ...zone ==> ["zone"]zoo ==> ["zo"]zoology ==> ["logy"]zoom ==> ["zo", "om"]zorn ==> ["zorn"]zoroaster ==> ["roaste", "oaster"]zoroastrian ==> ["oastri", "strian"]zounds ==> ["zounds"]zucchini ==> ["chin"]zurich ==> ["zurich"]zygote ==> ["zygote"]
functionnrls(byvals1)dimi,xiflen(s1)<2thennlrs=s:exitfunctions=lcase(replace(s1," ",""))redima(127)dimls:ls=len(s)start=1so=""ml=1a(asc(left(s,1)))=1fori=2tols+1ifi>lsthenrep=trueelsex=asc(mid(s,i,1))rep=a(x)<>0endififa(x)<>0thenif(i-start)>mlthenso=mid(s,start,i-start)ml=(i-start)elseif(i-start)=mlthenso=so&" "&mid(s,start,i-start)endifxx=a(x)forj=96to122:ifa(j)<=xthena(j)=0nextstart=xx+1endifa(x)=inextnrls=trim(so)eraseaendfunctionsubtest(f)wscript.stdout.writeline"Original: "&fwscript.stdout.writeline"Substrings: "&nrls(f)&vbcrlfendsubtest"dabale arroz a la zorra el abad"test"The quick brown fox jumps over the lazy dog"test"ae"test"aa"test"abdefghij"
Original: dabale arroz a la zorra el abadSubstrings: rozal lazorOriginal: The quick brown fox jumps over the lazy dogSubstrings: thequickbrownfOriginal: aeSubstrings: aeOriginal: aaSubstrings: a aOriginal: abdefghijSubstrings: abdefghij
fn substrings(s string) []string { n := s.len if n == 0 { return [""] } mut ss := []string{} for i in 0..n { for le := 1; le <= n-i; le++ { ss << s[i..i+le] } } return ss} fn distinct_runes(chars []rune) []rune { mut m := map[rune]bool{} for c in chars { m[c] = true } mut l := []rune{} for k,_ in m { l << k } return l} fn distinct_strings(strings []string) []string { mut m := map[string]bool{} for str in strings { m[str] = true } mut l := []string{} for k,_ in m { l << k } return l} fn main() { println("The longest substring(s) of the following without repeating characters are:\n") strs := ["xyzyabcybdfd", "xyzyab", "zzzzz", "a", ""] for s in strs { mut longest := []string{} mut longest_len := 0 for ss in substrings(s) { if distinct_runes(ss.runes()).len == ss.len { if ss.len >= longest_len { if ss.len > longest_len { longest = longest[..0] longest_len = ss.len } longest << ss } } } longest = distinct_strings(longest) println("String = '$s'") println(longest) println("Length = ${longest[0].len}\n") }}
Same as Wren entry
import"./seq"forLstvarsubstrings=Fn.new{|s|varn=s.countif(n==0)return[""]varss=[]for(iin0...n){for(lenin1..n-i)ss.add(s[i...i+len])}returnss}System.print("The longest substring(s) of the following without repeating characters are:\n")varstrs=["xyzyabcybdfd","xyzyab","zzzzz","a",""]for(sinstrs){varlongest=[]varlongestLen=0for(ssinsubstrings.call(s)){if(Lst.distinct(ss.toList).count==ss.count){if(ss.count>=longestLen){if(ss.count>longestLen){longest.clear()longestLen=ss.count}longest.add(ss)}}}longest=Lst.distinct(longest)System.print("String = '%(s)'")System.print(longest)System.print("Length =%(longest[0].count)\n")}
The longest substring(s) of the following without repeating characters are:String = 'xyzyabcybdfd'[zyabc, cybdf]Length = 5String = 'xyzyab'[zyab]Length = 4String = 'zzzzz'[z]Length = 1String = 'a'[a]Length = 1String = ''[]Length = 0