1. A method of operating a memory controller, the method comprising: receiving an input data sequence from a host; generating a coset representative sequence divisible into m-bit strings, where “m” is a natural number greater than 1, from the input data sequence; performing a first XOR operation on each of the m-bit strings in the coset representative sequence; calculating all possible branch metrics according to a result of the first XOR operation; determining a survivor path sequence based on the all possible branch metrics; performing a second XOR operation on the coset representative sequence and the survivor path sequence to generate an output sequence; and providing write data sequence based on the output sequence to a non-volatile memory device, wherein the calculating the all possible branch metrics comprises: calculating the all possible branch metrics using a first programmed state sequence determined on the basis of the first XOR operation and a second data sequence to be stored in a first word line together with the output sequence, and a second programmed state sequence determined on the basis of page data bits that have been stored in a second word line.