Hola, en relación a las dudas:
a) Correcto como indicas
b) El uso del this: hay casos en los que no es necesario (como este), pero lo puedes poner si quieres. Si no es necesario, ¿para qué ponerlo? Simplemente para remarcar o dejar claro que te estás refiriendo al objeto-en-sí, es decir, a un atributo o método de la propia clase y no a otra cosa (un parámetro u otra cosa). this actúa eliminando ambiguedades cuando existen, pero se puede poner siempre que quieras, no es algo que sólo puedas usar para eliminar ambiguedades.
Con super.equals estamos invocando el método equals de la clase padre como si fuera un método propio de la clase hijo. El equals de la clase padre pierde visibilidad en la clase hijo debido a que está sobreescrito. La forma de poder invocarlo es usar la palabra clave super. De esta forma indicamos que el método equals de la clase padre está embebido en la clase hijo, es decir, que para dos objetos ser iguales tiene que cumplirse la condición de igualdad de la clase padre y además algunas cosas suplementarias.
Tú puedes escribir: if ( this.IdProfesor.equals(tmpProfesor.IdProfesor) ) {
en este caso sin invocar super, pero estás cambiando las condiciones de igualdad. Podrías hacerlo si se considerara oportuno.
Respecto a si Java busca automáticamente métodos hacia las clases padres: sí, siempre que no estén sobreescritos. En este caso está sobreescrito, por tanto no usará el método de la clase padre a no ser que nosotros se lo indiquemos.
Sobre la última duda: ¿una recursión constante? Si te refieres a si el método equals se llama a sí mismo la respuesta es no. El método equals de persona es una cosa, el método equals de un String otra. Cuando escribimos this.nombre.equals(tmpPersona.nombre) estamos usando el método equals de String. Son métodos sobreescritos, por tanto su significado depende de qué objeto sea el que lo invoque.
Saludos
