This is a job for join using the print unpairable lines (-a) argument. Then we keep the lines ending with a space, and remove that space. To avoid using temporary files, we use bash process substitution.
join -a 1 -j 1 -o 1.1,2.1 \
<(tr " " "\n" <<< "$CATSNDOGS" | sort) \
<(tr " " "\n" <<< "$DOGS" | sort) | sed -e '/ $/!d;s/ //'
It looses the initial order of $CATSNDOGS, but we could easily add a cat -n and a sort to get back the initial ordering.
To put that back in a variable, do:
CATS="$(join -a 1 -j 1 -o 1.1,2.1 \
<(tr " " "\n" <<< "$CATSNDOGS" | sort) \
<(tr " " "\n" <<< "$DOGS" | sort) | sed -e '/ $/!d;s/ //' | paste -s -d " ")"