g | x | w | all
Bytes Lang Time Link
022Nekomata250903T024232Zalephalp
177JavaScript ES6250902T075317ZArnauld
067Charcoal250901T133208ZNeil

Nekomata, 22 bytes

ʷ{ĕᵈ{ĕ;;$}=¿ÐᶠN,}ØcŞ#å

Attempt This Online!

Extremely slow for long inputs.

ʷ{ĕᵈ{ĕ;;$}=¿ÐᶠN,}ØcŞ#å
ʷ{              }       Loop until failure:
  ĕ                         Take one item out of the input
   ᵈ{    }                  Apply the following to the original input:
     ĕ                          Take another item out of it
      ;;                        Split it into three parts
        $                       Swap the last part and the middle part
          =                 Check if the middle part equals to the first taken item
           ¿Ð               If so, pair the two other parts into a list
             ᶠN             Remove empty lists
               ,            Join it with the remaining input
                 Øc     Prepend an empty list (so that there is always a longest item)
                   Ş    Find the longest item
                    #   Get its length
                     å  Find the minimal possible result

If there are multiple smallest lengths, Nekomata will output the same result multiple times. You can add the -1 flag to output only the first one.

JavaScript (ES6), 177 bytes

f=(a,s=m=a)=>a.map((p,i)=>p&&a.map((q,j)=>i-j&&q.replace(RegExp(p,'g'),(_,k)=>f(b=[...a],b[i]=q.slice(b[j]=q.slice(k+s[i]),k)))),M=Math.max(...s=a.map(s=>s.length)),M>m?0:m=M)|m

Try it online!

Commented

f = (                     // f is a recursive function taking:
  a,                      //   a[] = input array
  s =                     //   s = variable reserved in this scope
  m = a                   //   m = the minimum value we're looking for,
) =>                      //       initially NaN'ish
a.map((p, i) =>           // for each word p at index i in a[]:
  p &&                    //   abort if p is empty
  a.map((q, j) =>         //   for each word q at index j in a[]:
    i - j &&              //     abort if i = j
    q.replace(            //     search in q ...
      RegExp(p, 'g'),     //       ... all occurrences of p
      (_, k) =>           //       for each match at position k,
      f(                  //       do a recursive call:
        b = [...a],       //         with b[] = copy of a[] where:
        b[i] = q.slice(   //           b[i] = string before the match
          b[j] = q.slice( //           b[j] = string after the match
            k + s[i]      //         using s[i] for the length of p
          ),              //         b[j] is zero'ish and can therefore
          k               //         be used as the 1st argument of the
        )                 //         other slice()
      )                   //       end of recursive call
    )                     //     end of replace()
  ),                      //   end of inner map()
  M = Math.max(           //   M is the maximum value in:
    ...s = a.map(s =>     //     the array s[] which contains:
      s.length            //       the lengths of the strings in a[]
    )                     //     end of map()
  ),                      //   end of Math.max() (-∞ if a[] is empty)
  M > m ? 0               //   do nothing if M > m
        : m = M           //   otherwise, update m to M
)                         // end of outer map()
| m                       // return m coerced to an integer (-∞ → 0)

Charcoal, 67 bytes

⊞υAFυFLιFΦLι⁻μκF⌕A§ικ§ιλ⊞υ⁺Φι∧⁻ξκ⁻ξλΦ⟦…§ικμ✂§ικ⁺μL§ιλ⟧νI⌊Eυ∧Lι⌈EιLλ

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

⊞υAFυ

Traverse all possible reductions starting from the input.

FLιFΦLι⁻μκ

Select all pairs of strings in the current list.

F⌕A§ικ§ιλ

Loop over all possible break points.

⊞υ⁺Φι∧⁻ξκ⁻ξλΦ⟦…§ικμ✂§ικ⁺μL§ιλ⟧ν

Remove the two strings from the list and add the prefix and suffix (where not empty).

I⌊Eυ∧Lι⌈EιLλ

Output the minimum maximum length.