g | x | w | all
Bytes Lang Time Link
162Python241216T052308Ztsh
056K ngn/k250103T175145Zcoltim
143Python241218T024911ZAlbert.L
472Java241216T151048ZAbhay Tr
070K ngn/k241220T021726Zatt
174Python 3241214T203807ZUri Gran
302Wolfram Language Mathematica241216T144057ZIntroduc
221Maple241218T174859Zdharr
017Jelly241216T001958ZJonathan
162Retina241214T220239ZNeil
02305AB1E241217T083135ZKevin Cr
269Google Sheets241215T072334Zdoubleun
030Japt v2.0a0 h241216T110120ZShaggy
049Charcoal241215T082232ZNeil
128JavaScript ES6241215T002804ZArnauld
110Perl 5 ap241215T055008ZXcali

Python, 162 bytes

lambda s:min((g:=lambda p,a,b:a and g(p+f' {a}'[t:=a[0]==b[:1]],a[1:],b[t:])or[b,-len(w),p])('',re.sub(fr'\b{w}\b',w.upper(),s),w)for w in s.split())[2];import re

Attempt This Online!

-5 bytes by Jonathan Allan -2 bytes by STerliakov

K (ngn/k), 56 bytes

{r@*<+/'1+^r:w@'<'>'w{y_x,y~:*x}/'x/'+(,'w)@'=#w:x\y}" "

Try it online!

Hat-tip @tubular for trimming a bunch off.

Another adaptation of my Speed of Lobsters golf, with pieces lifted from @att's answer.

Python, 143 bytes

lambda s:max([(j:=0)or''.join(w[j:(j:=j+(z==w[j:j+(v!=w)]))]or' 'for v in s.split()for z in v+' ')[:0-j//len(w)]for w in s.split()],key=sorted)

Attempt This Online!

Still feels like there is some slack left.

History:

Python, 147 bytes

lambda s:max([(j:=0)or''.join(' '*(z!=w[j:j+1]or v==w)or z[:(j:=j+1)]for v in s.split()for z in v+' ')[:-(w[:j]==w)]for w in s.split()],key=sorted)

Attempt This Online!

This one avoids the super-expensive substring replacement. Turns out that is worth jumping through a hoop or two.

Python, 151 bytes

lambda s:max([''.join(D[c==w[j:j+1]and(j:=j+1)]for c in f' {s} '.replace(D,D.upper()))[1:-(w[j:]<D)]for w in s.split()if[j:=0,D:=f' {w} ']],key=sorted)

Attempt This Online!

Python, 152 bytes

lambda s:max([''.join(D[c==[*w,0][j]and(j:=j+1)]for c in f' {s} '.replace(D,D.upper()))[1:-(w[j:]<D)]for w in s.split()if[j:=0,D:=f' {w} ']],key=sorted)

Attempt This Online!

Python, 153 bytes

lambda s:max([''.join(D[c==[*w,0][j]and(j:=j+1)]for c in f' {s} '.replace(D,len(D)*' '))[1:-(w[j:]<D)]for w in s.split()if[j:=0,D:=f' {w} ']],key=sorted)

Attempt This Online!

Python, 160 bytes

lambda s:max([''.join(c*(c==D[j-1:j]!=[j:=j+1])or' 'for c in f' {s} ~'.replace(D,len(D)*' '))[1:j//len(D)*-2]for w in s.split()if[j:=1,D:=' %s '%w]],key=sorted)

Attempt This Online!

Java , 472 bytes


> edit : addition of lastIndexmatcher so it ensures wd in orderr. 

import java.util.Scanner;

class Subsequenc {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);

        // Input the string and the word
        System.out.print("Enter the string: ");
        String str = sc.nextLine();

        System.out.print("Enter the word: ");
        String wd = sc.nextLine();

        // Result array initialized with spaces
        char ch[] = new char[str.length()];
        for (int i = 0; i < ch.length; i++) {
            ch[i] = ' ';
        }

        // Track the position of the last matched character
        int lastMatchedIndex = -1;

        // Match logic
        for (int i = 0; i < wd.length(); i++) {
            char currentChar = wd.charAt(i);
            boolean found = false;
            for (int j = lastMatchedIndex + 1; j < str.length(); j++) {
                if (str.charAt(j) == currentChar) {
                    ch[j] = currentChar; // Add the matched character
                    lastMatchedIndex = j; // Update the last matched index
                    found = true;
                    break; // Move to the next character in wd
                }
            }
            if (!found) {
                // If a character in wd isn't found after lastMatchedIndex, stop processing
                break;
            }
        }

        // Print the result
        for (char c : ch) {
            System.out.print(c);
        }
    }
}

K (ngn/k), 70 bytes

{*<c!+/'^c:a{(,'y)@'(#*|b)|x~':b:x{(*x=y)_x}\y}'x/'+(,'a)@'=#a:x\y}" "

Try it online!

Wonder if there's a non-brute-force better way.

                                                            a:x\y  words
                                               x/'+(,'a)@'=#       each whited out in input
          a{                                 }'                    subsequences:
            (,'y)@'       x~':b:x{(*x=y)_x}\y                        fill in a subsequence
                   (#*|b)|                                           only if all chars present
*<c!+/'^c:                                                         min by #spaces

Python 3, 186 174 bytes

A quick not-very-golfed solution; I expect it's possible to do much better. Might try again if I get some time. (PS Thanks @tsh for saving 11 bytes, and @jonathan-allan for saving 1 more.)

import re
def f(s):
 for w in sorted(s.split(),key=len)[::-1]:
  t=re.sub(fr"\b{w}\b",w.upper(),s);o=""
  for c in w:n=t.find(c);o+=" "*n+c;t=t[n+1or len(t):]
  if~n:return o

Try it online!

Wolfram Language (Mathematica), 302 bytes

f[i_]:=(s=StringSplit[i];c=First@MaximalBy[Cases[s,Alternatives@@LongestCommonSequence@@@Transpose@{StringRiffle@Delete[s,#]&/@Range@Length@s,s}],StringLength];j=1;StringJoin@@Select[Map[If[#==(Characters@c)[[j]],j+=1;#," "]&,Characters@StringRiffle@(s/.c->StringRepeat[" ",StringLength[c]])],StringQ])

Try it online!

Maple, 221 bytes

proc(s)uses StringTools;b:=" ";for u in sort(Words(s),length)do L:=length(u);t:=Substitute(cat(s,b),cat(u,b),cat(b$L+1));j:=1;c:=cat([for i in t do if i=u[j] then j++;i else b fi od][]);`if`(j-1=L,(g:=c[..-2]),x)od;g end;
proc(s) uses StringTools;                # input string s
 b:=" ";  
 for u in sort(Words(s),length) do       # sort words in increasing length
                                         # so last and longest success is returned
  L:=length(u);  
  t:=Substitute(cat(s,b),cat(u,b),cat(b$L+1)); # replace word with spaces;
                                         # pad word and s with space so doesn't
                                         # substitute within a longer word
  j:=1;  
  c:=cat([for i in t do if i=u[j] then j++;i else b fi od][]); # scan with i
                                         # pointing in string and j in word
  `if`(j-1=L,(g:=c[..-2]),x)             # success recorded in g if word was
                                         # finished (strip previously added space)
 od;  
 g                                       # return g  
end;  

Jelly,  30 29 28 21 19  17 bytes

-7 porting Kevin Cruijssen's approach in their 05AB1E answer (as proposed in the "Could probably be..." note above my original answer, below). Also -4 more golfing this.

JŒPṬoḲix@ʋƇo¬ao⁶

A monadic Link that accepts a list of characters and yields a list of characters.

Try it online! (although it's too slow for the longer test cases).

How?

JŒPṬoḲix@ʋƇo¬Ṫao⁶ - Link: Plaintext
J                 - indices of {Plaintext} -> AllIndices
 ŒP               - powerset of {AllIndices} (shortest to longest)
   Ṭ              - untruth -> AllMasks (each with ones at the chosen indices and
                                         zeros elsewhere up to the last chosen index)
          Ƈ       - keep those of {AllMasks} for which:
         ʋ        -   last four links as a dyad - f(Mask, Plaintext):
    o             -     {Mask} logical OR {Plaintext} (vectorises) 
                        -> Masked (Plaintext with ones in place of chosen indices)
     Ḳ            -     split {Masked} at space characters -> WordsOfMasked
       x@         -     {Plaintext} repeat {Mask} (vectorises)
                        -> Substring (i.e. the characters at the chosen indices)
      i           -     first 1-indexed index of {Substring} in {WordsOfMasked}
                        ...or 0 if not found
                    -> ValidMasks (ordered from fewest to most set bits)
            ¬     - {Plaintext} logical NOT -> Zeros = [0,0,...,0] (Plaintext's length)
           o      - {ValidMasks} logical OR {Zeros} (vectorises)
                    (right pads each mask with zeros to the length of Plaintext)
             Ṫ    - tail -> ValidMaskWithMaximalSetBits
              a   - {ValidMaskWithMaximalSetBits} logical AND {Plaintext} (vectorises)
                    -> X = Plaintext with zeros where we want spaces
               o⁶ - {X} logical OR with a space character (vectorises)
                    (replaces the zeros with spaces)

Original, 28 bytes

-1 inspired by Niel's comment about the original having two helper Links :)

Could probably be slightly terser by using a more bute-force approach (think partitions or powersets) - EDIT: yep, see above.

⁶µḲ¬i¦KẹⱮŒpʋⱮ`ẎQṢ$ƑƇLÞṪḟ@Jµ¦

A monadic Link that accepts a list of characters and yields a list of characters.

Try it online!

How?

⁶µ...µ¦ - Link: Plaintext         e.g: "a word is missing mate"
      ¦ - sparse application to {Plaintext}...
 µ   µ  - ...to indices: monadic chain - f(Plaintext) -> SpaceIndices
⁶       - ...apply: space character -> "           i s        "

Ḳ¬i¦KẹⱮŒpʋⱮ` - start of the monadic chain: Plaintext
Ḳ            - split {Plaintext} at space characters -> PlaintextAsWords
          Ɱ` - map across TrialWord in {PlaintextAsWords} with:
         ʋ   -   last four links as a dyad - f(PlaintextAsWords, TrialWord}
                 e.g. f(["a","word","is","missing","mate"], "is")
   ¦         -     sparse application to {PlaintextAsWords}...
  i          -     ...at indices: first index of {TrialWord} in {PlaintextAsWords}
 ¬           -     ...apply: logical NOT (vectorises)
    K        -     join with space characters -> RedactedPlaintext, e.g:
                   ['a',' ','w','o','r','d',' ',0,0,' ','m','i','s','s','i','n','g',' ','m','a','t','e']
      Ɱ      -     map across Character in {TrialWord} with:
     ẹ       -       indices of {Character} in {RedactedPlaintext}
                   [[12,15],[13,14]]
       Œp    -     Caterisan product -> AllIndexPicksMakingTrialWord
                   [[12,13],[12,14],[15,13],[15,14]]
               -> AllIndexPicksMakingTrialWordForEachWord
                  [[[20]],[],[[12,13],[12,14],[15,13],[15,14]],[],[]]

ẎQṢ$ƑƇLÞṪḟ@J - the rest of the monadic chain: AllIndexPicksMakingTrialWordForEachWord
Ẏ            - tighten
               [[20],[12,13],[12,14],[15,13],[15,14]]
     Ƈ       - keep those for which:
    Ƒ        -   is invariant under?:
   $         -     last two links as a monad:
 Q           -       deduplicate
  Ṣ          -       sort
               [[20],[12,13],[12,14]
      LÞ     - sort by length (to place the longest ones on the right)
        Ṫ    - tail -> KeepCharactersAt
               [12,14]
           J - indices {Plaintext} -> AllIndices
         ḟ@  - {AllIndices} filter discard {KeepCharactersAt}
               -> SpaceIndices
               [1,2,3,4,5,6,7,8,9,10,11,13,15,16,17,18,19,20,21,22]

Retina, 189 180 162 bytes

L$`\b((\w)+)\b(?=(.)*(?<=(?(2)$)((?<-2>\2)|.)*\1(?<-3>(?<-2>\2)|.)*))
$& $`$.&* $'
N^$`
$.&
0G`
|""L$`\G(?<=(.)*)(\w)(?=\w* ((?<-1>\1)|.)*?(?(1)$)(.*?)\2)
$.4* $2

Try it online! Link includes test cases. Explanation:

L$`\b((\w)+)\b(?=(.)*(?<=(?(2)$)((?<-2>\2)|.)*\1(?<-3>(?<-2>\2)|.)*))
$& $`$.&* $'

Find all of the words that are subsequences of the remaining string. .NET balancing groups are used twice, firstly ?<-2> matches the subsequence and secondly ?<-3> ensures that the original word is skipped at the right place when matching the subsequence. (Note that the lookbehind is processed right-to-left, so that the (?(2)$) is actually the last part of the regex.) For each word, prefix it to the input with that word replaced with spaces.

N^$`
$.&
0G`

Sort in reverse order of length and keep only the longest word.

|""L$`\G(?<=(.)*)(\w)(?=\w* ((?<-1>\1)|.)*?(?(1)$)(.*?)\2)
$.4* $2

Find the subsequence and output only those letters with the appropriate amount of spacing.

05AB1E, 24 23 bytes

ā<DæéR.ΔÎrǝð¡IyèJå}Kðsǝ

-1 byte fixing a bug found by @JonathanAllan (yes, -1 byte, not +1 😅)

(Don't) try it online.
To speed it up slightly, so it can at least output some test cases: try it online or verify multiple smaller test cases at once.

Explanation:

ā<              # Push a list in the range [0, (implicit) input-length)
  D             # Duplicate this indices-list
æ               # Pop and get the powerset of the copy
 éR             # Sort the from longest to shortest
   .Δ           # Pop and find the first that's truthy for:
     Î          #  Push 0 and the input-string
      r         #  Reverse the stack order
       ǝ        #  Insert the 0 at the current indices into the input
        ð¡      #  Then split on spaces
          I     #  Push the input-string again
           yè   #  Get the characters at the current indices
             J  #  Join this list of characters to a string
              å #  Check if it's in the list
    }K          # After the find_first: remove those indices from the full indices-list
      ðsǝ       # Insert spaces at all remaining indices in the (implicit) input 
                # (after which the result is output implicitly)

The (slightly) faster version has éR replaced with I#€gêù€`R:

 I              # Push the input-string
  #             # Split it on spaces
   €g           # Get the length of each word
     ê          # Uniquify and sort those lengths (smallest to largest)
      ù         # Only keep the powerset-lists of those lengths
       €`       # Flatten the list one level down
         R      # Reverse the list, so the order is from longest to shortest

Google Sheets, 269 bytes 313 bytes

=let(b,"(.*)",w,tocol(split(A1," ")),sort(reduce(,sort(w,len(w),0),lambda(a,t,let(l,len(t),s,substitute(A1,t,rept(" ",l),1),p,b&join(b,mid(t,sequence(l),1))&b,o,join("_",regexextract(s,p)),i,sequence(len(o)),if(a=0,ifna(join(,if(mid(o,i,1)="_",mid(s,i,1)," "))),a))))))

Put the phrase in cell A1 and the formula in B1.

screenshot

The formula uses simple regexes only and doesn't rely on lookaround or backtracking. Bonus: works for outruled repetitions like one to one and example example as well.

Ungolfed:

=let( 
  words, tocol(split(A1, " ")), 
  sorted, sort(words, len(words), 0), 
  sort(reduce(, sorted, lambda(a, t, let( 
    length, len(t), 
    stripped, substitute(A1, t, rept(" ", length), 1), 
    letters, mid(t, sequence(length), 1), 
    pattern, "(.*)" & join("(.*)", letters) & "(.*)", 
    opposite, join("_", regexextract(stripped, pattern)), 
    i, sequence(len(opposite)), 
    if(a = 0, 
      ifna(join(, if(mid(opposite, i, 1) = "_", mid(stripped, i, 1), " "))), 
      a 
    ) 
  ))))
)

Japt v2.0a0 -h, 45 39 35 31 30 bytes

¸£¸hYXç)¸Ë¶XÎ?X=ÅD:SÃpÂ!XÃñè\a

Try it or run all test cases

¸£¸hYXç)¸Ë¶XÎ?X=ÅD:SÃpÂ!XÃñè\a     :Implicit input of string U
¸                                  :Split on spaces
 £                                 :Map each X at index Y
  ¸                                :  Split U on spaces
   hY                              :  Replace the element at index Y with
     Xç                            :    Fill X with spaces
       )                           :  End replace
        ¸                          :  Join with spaces
         Ë                         :  Map each D
          ¶                        :    Is equal to
           XÎ                      :      First character of X
             ?                     :    If true
              X=                   :      Reassign to X
                Å                  :        Remove first character from X
                 D                 :      Return D
                  :                :    Else return
                   S               :      Space
                    Ã              :  End inner map
                     p             :  Repeat
                      Â            :    Bitwise NOT of bitwise NOT of
                       !X          :    Logical NOT of X
                         Ã         :End outer map
                          ñ        :Sort by
                           è       :  Count of
                            \a     :    RegEx /[a-z]/g
                                   :Implicit output of last element

Charcoal, 59 49 bytes

F⪪θ «≔⪪⮌ι¹ηP×⭆⪫E⪪θ ⎇⁼ικ⭆κ κ ⎇∧η⁼κ§η±¹⊟ηψ∧¬η›LιLKA

Try it online! Link is to verbose version of code. Explanation:

F⪪θ «

Split the input into words and loop over each word.

≔⪪⮌ι¹η

Start with all letters remaining to be matched. (The letters are reversed so that they can be easily removed as they are matched.)

P×⭆⪫E⪪θ ⎇⁼ικ⭆κ κ ⎇∧η⁼κ§η±¹⊟ηψ∧¬η›LιLKA

Replace the word in the original string with spaces, then replace all of the characters with nulls (which print as spaces but don't count as being printed, so the length of the previous result can be counted as the number of printed characters) except the letters from the word which are kept as they are matched. If this matched all of the letters, and this word is longer than any previously output word, then output the result, overwriting any previous result.

JavaScript (ES6), 128 bytes

-3 thanks to @l4m2

s=>s[R="replace"](/\w+/g,n=w=>w[q=s[R](RegExp(`\\b${w}\\b`),w[R](e=/./g,i=0))[R](e,c=>c==w[i]?++i&&c:" "),i]||n>i||(n=i,b=q))&&b

Try it online!

Commented

s =>                 // s = input string
s[R = "replace"](    // replace in s
  /\w+/g,            // look for words
  n =                // n = best length so far, initially NaN'ish
  w =>               // for each word w in s:
  w[                 //   test w[i]:
    q =              //     q is the string obtained by
    s[R](            //     replacing in s:
      RegExp(        //       the (only) occurrence of w
        `\\b${w}\\b` //       surrounded by word boundaries
      ),             //
      w[R](          //       with w where ...
        e = /./g,    //         each character
        i = 0        //         is replaced with '0'
      )              //       end of replace()
    )                //     end of replace()
    [R](             //     replace again:
      e,             //       each ...
      c =>           //       ... character c with:
      c == w[i] ?    //         if c is w[i]:
        ++i && c     //           c itself (and increment i)
      :              //         else:
        " "          //           a space
    ),               //     end of replace()
    i                //     i is the actual index for our test
  ] ||               //   do nothing if w[i] is defined
                     //   (i.e. the subsequence is incomplete)
  n > i ||           //   or n is greater than i
                     //   (i.e. the best word b is longer)
  (n = i, b = q)     //   otherwise, set n to i and b to q
) && b               // end of replace(); return b

Perl 5 -ap, 110 bytes

$"=".*";map{@;=/./g;$m=$_,@l=@;if"@F"=~s/\b$_\b//r=~@;&@;>@l}@F;s/\b$m\b/' 'x@l/e;s/./$&eq$l[0]?shift@l:' '/ge

Try it online!