I just tried rewriting this and I can't find a good way to do it.  The problem is P2SH addresses can change even though they use the same public keys.

For example, a 2-of-2 multisig P2SH where the first time you do, keyA keyB, and the second time you do, keyB keyA.  That gives you a different hash (address), but the same public keys are used.  Once the P2SH output is spent (revealing the public keys), you can then look for other spent outputs that use those public keys.

Now, it's true that the receiver usually[1] doesn't reveal his public key during the transaction.  That's why I said, "(in some form)".  The spender can, of course, watch the receiver's address until he spends the output, at which point he does have to reveal his public key.  (Which will allow you to link it to other forms of that public key.)

I'm going to leave this the way it is and maybe change some of the later sentences which refer to addresses so the terminology in this section is more consistent.

[1] pay-to-pub-key (no hash) transactions are IsStandard() even though there only really used for coinbase.