Starts with aa or bb. Ends with it (back reference). And has no it in the middle.
It is ok without “or” and back reference — aa.*?(?!aa).*?aa
But it does not work with them:
(aa|bb).*?(?!\1).*?\1
echo preg_match("@(aa|bb).*?(?!\\1).*?\\1@", 'aaxxaaxaa'); // 1 ??
echo preg_match("@(aa|bb).*?(?!\\1).*?\\1@", 'aaxxxaa'); // 1
What is wrong?
You need to check your negative condition for every character.
You also need to add anchors.
See it working online: ideone