South Sudan's army has retaken the key provincial capital of Malakal from rebels after weeks of fighting.