Monday Mini-Golf #5: Don't DO try this at home
Pip, 138 140 bytes

Yeesh, that cannot/knot distinction is tricky.

x:"ca wo ai sha i'm you're"^sY"CAN0WILL0AM0SHALL0I AM0YOU ARE"^0OqR-`([\w']+)( no|n'|(?&lt;=can)no)t\b`{++i"&lt;s&gt;".a."&lt;/s&gt;".s.((yx@?LCb)|UCb)}s.i


Reads a line from stdin, outputs to stdout. The regex:

`([\w']+)( no|n'|(?&lt;=can)no)t\b`


matches a word (including apostrophes) followed by one of three things:


 not
n't
not without a space, provided the first half of the word was can


The - operator on a regex makes it case-insensitive.

Matches are replaced with the result of the following function. (Note: within the function, a is the whole match and b is capture group 1.)

{++i"&lt;s&gt;".a."&lt;/s&gt;".s.((yx@?LCb)|UCb)}
 ++i                                   Increment counter
    "&lt;s&gt;".a."&lt;/s&gt;"                     Return entire match wrapped in HTML tags...
                  .s.(             )   plus space, plus the following:
                           LCb         Lowercase first capture group
                        x@?            Find its index in list x of special cases (nil if
                                         not in list)
                      (y      )        Use that as index into list y of replacements
                               |UCb    If it wasn't a special case, this is nil, and we
                                         instead use uppercase(b)


Once the modified string is done, we also output a space and the number of replacements i.