Podrías meter en un array palabras que son un insulto aunque vayan junto a otras palabras, por ejemplo eresunidiota, idiota no es lo mismo que crepúsculo, que al final de una palabra forma otra verdaderamente.
Así que se me ocurre hacer un array para el primer tipo de insultos y recorrerlo usando stristr. Para palabras como culo, recorrer usando un explode que separe por espacios e identifique solamente la palabra malsonante.
Para evitar que use palabras como eresunculo se me acaba de ocurrir también otra cosa. Parsear un diccionario web en linea, como puede ser
http://www.rae.es/rae.htmlSi la palabra no existe, como es el caso de eresunculo, y stristr te devuelve que culo está en tu string de insultos, que deniegue la palabra, pues realmente no tiene ningún significado.. Y luego con un simple if que vea si la palabra es culo a secas y que la deniegue igualmente. Lo que pasa es que para parsear el diccionario, o bien haces muy bien el script, o se va a demorar un poco..
Un saludo.