3 saved 4 bytes
source | link

JavaScript (ES6), 130 130  126 bytes

L=>W=>L.every(a=>a.every(x=>(W+'').match(x,a.map(y=>s+='|'+x+y))),p=s=1)&W.every(w=>w[2]&&(+p||w[0]==p.slice(-1))&w=>w[2]&&p|w[0]==p&!w.match(s,p=w.slice(-1)))

Try it online!Try it online!

W.every(w =>              // for each word w in W[]:
  w[2] && (                //   is this word at least 3 characters long?
  p | +p ||                 //  // unless this is it the 1stfirst word,? make(p sure= that:1)
    w[0] == p.slice(-1) &             //   or does it startsstart with the last letter of the previous word?
  ) &      !w.match(               //   and finally make sure that: ...
  !w.match(  s,                    //     ... it doesn't contain any invalid pair of letters
    p = w.slice(-1)       //     and update p =to the last letter of w
  )                       //   update pend toof wmatch()
)                         // end of every()

JavaScript (ES6), 130 bytes

L=>W=>L.every(a=>a.every(x=>(W+'').match(x,a.map(y=>s+='|'+x+y))),p=s=1)&W.every(w=>w[2]&&(+p||w[0]==p.slice(-1))&!w.match(s,p=w))

Try it online!

W.every(w =>              // for each word w in W[]:
  w[2] && (               //   is this word at least 3 characters long?
    +p ||                 //   unless this is the 1st word, make sure that:
    w[0] == p.slice(-1)   //   it starts with the last letter of the previous word
  ) &                     //   and finally make sure that:
  !w.match(s,             //   it doesn't contain any invalid pair of letters
              p = w)      //   update p to w
)                         // end of every()

JavaScript (ES6),  130  126 bytes

L=>W=>L.every(a=>a.every(x=>(W+'').match(x,a.map(y=>s+='|'+x+y))),p=s=1)&W.every(w=>w[2]&&p|w[0]==p&!w.match(s,p=w.slice(-1)))

Try it online!

W.every(w =>              // for each word w in W[]:
  w[2] &&                 //   is this word at least 3 characters long?
  p |                     //   is it the first word? (p = 1)
  w[0] == p &             //   or does it start with the last letter of the previous word?
  !w.match(               //   and finally make sure that ...
    s,                    //     ... it doesn't contain any invalid pair of letters
    p = w.slice(-1)       //     and update p to the last letter of w
  )                       //   end of match()
)                         // end of every()
2 added a commented version
source | link

Step 1

We first iterate over \$L\$ to build a pipe-separated string \$s\$ consisting of all invalid pairs of letters. While doing so, we also make sure that each letter appears at least once in some word.

L.every(a =>              // for each group of letter a[] in L[]:
  a.every(x =>            //   for each letter x in a[]:
    (W + '')              //     coerce W[] to a string
    .match(               //     and test whether ...
      x,                  //       ... x can be found in it
      a.map(y =>          //       for each letter y in a[]:
        s += '|' + x + y  //         append '|' + x + y to s
      )                   //       end of map()
    )                     //     end of match()
  ),                      //   end of inner every()
  p = s = 1               //   start with p = s = 1
)                         // end of outer every()

Step 2

We now iterate over \$W\$ to test each word.

W.every(w =>              // for each word w in W[]:
  w[2] && (               //   is this word at least 3 characters long?
    +p ||                 //   unless this is the 1st word, make sure that:
    w[0] == p.slice(-1)   //   it starts with the last letter of the previous word
  ) &                     //   and finally make sure that:
  !w.match(s,             //   it doesn't contain any invalid pair of letters
              p = w)      //   update p to w
)                         // end of every()

Step 1

We first iterate over \$L\$ to build a pipe-separated string \$s\$ consisting of all invalid pairs of letters. While doing so, we also make sure that each letter appears at least once in some word.

L.every(a =>              // for each group of letter a[] in L[]:
  a.every(x =>            //   for each letter x in a[]:
    (W + '')              //     coerce W[] to a string
    .match(               //     and test whether ...
      x,                  //       ... x can be found in it
      a.map(y =>          //       for each letter y in a[]:
        s += '|' + x + y  //         append '|' + x + y to s
      )                   //       end of map()
    )                     //     end of match()
  ),                      //   end of inner every()
  p = s = 1               //   start with p = s = 1
)                         // end of outer every()

Step 2

We now iterate over \$W\$ to test each word.

W.every(w =>              // for each word w in W[]:
  w[2] && (               //   is this word at least 3 characters long?
    +p ||                 //   unless this is the 1st word, make sure that:
    w[0] == p.slice(-1)   //   it starts with the last letter of the previous word
  ) &                     //   and finally make sure that:
  !w.match(s,             //   it doesn't contain any invalid pair of letters
              p = w)      //   update p to w
)                         // end of every()
1
source | link

JavaScript (ES6), 130 bytes

Takes input as (letters)(words). Returns \$0\$ or \$1\$.

L=>W=>L.every(a=>a.every(x=>(W+'').match(x,a.map(y=>s+='|'+x+y))),p=s=1)&W.every(w=>w[2]&&(+p||w[0]==p.slice(-1))&!w.match(s,p=w))

Try it online!