// File: medvedevgroup[P]varmatch/src/wholegenome.cpp
// Function: WholeGenome::needleman_wunsch(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&)
int WholeGenome::needleman_wunsch(string S1, string S2, string &R1, string &R2)
{
    int M = S1.length();
    int N = S2.length();
    /*
    0MMMMMMMMMMMMMMMM
    N
    N
    N
    N
    N
    N
    so the matrix is N*M
    */
    int **score = new int *[N+1];
    for (int i = 0; i <= N; i++)
    {
        score[i] = new int [M+1];
    }

    char **trackBack = new char *[N+1];
    // * for match, - for ->, | for moving downward
    for (int i = 0; i <= N; i++)
    {
        trackBack[i] = new char [M+1];
    }
    R1 = "";
    R2 = "";
    initialize_score_matrix(score, trackBack, M, N);

    for (int i = 1; i <=N; i++)
    {
        for (int k = 1; k <= M; k++)
        {
            char S1_k = S1[k-1];
            char S2_i = S2[i-1];
            int matchingCost = score[i-1][k-1];
            if(S1_k != S2_i) matchingCost--;
            int rightCost = score[i][k-1] - 1;
            int downCost = score[i-1][k] - 1;
            if (matchingCost > rightCost && matchingCost > downCost)
            {
                score[i][k] = matchingCost;
                trackBack[i][k] = '*';
            }else if(rightCost >= downCost)
            {
                score[i][k] = rightCost;
                trackBack[i][k] = '-';
            }else
            {
                score[i][k] = downCost;
                trackBack[i][k] = '|';
            }
        }
    }

    //trackBack
    int n = N;
    int m = M;
    while(n > 0 || m > 0)
    {
        if (trackBack[n][m] == '*')
        {
            R1 += S1[m-1];
            R2 += S2[n-1];
            n--;
            m--;
        }else if(trackBack[n][m] == '-')
        {
            R1 += S1[m-1];
            R2 += '-';
            m--;
        }else if(trackBack[n][m] == '|')
        {
            R1 += '-';
            R2 += S2[n-1];
            n--;
        }
    }
    reverse(R1.begin(), R1.end());
    reverse(R2.begin(), R2.end());

    int result = score[N][M];

    for (int i = 0; i <= N; i++)
    {
        delete score[i];
        delete trackBack[i];
    }

    delete score;
    delete trackBack;

    return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rsi, -0xb8(%rbp)
movq %rdi, %rax
movq -0xb8(%rbp), %rdi
movq %rdi, -0xb0(%rbp)
movq %rdx, -0xa0(%rbp)
movq %rax, -0x8(%rbp)
movq %rdi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xa8(%rbp)
callq 0x6630
movq -0xa0(%rbp), %rdi
movl %eax, -0x2c(%rbp)
callq 0x6630
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
addl $0x1, %eax
cltq
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x6040
movq %rax, -0x38(%rbp)
movl $0x0, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x30(%rbp), %eax
jg 0x1d7bf
movl -0x2c(%rbp), %eax
addl $0x1, %eax
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x6040
movq %rax, %rdx
movq -0x38(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x1d774
movl -0x30(%rbp), %eax
addl $0x1, %eax
cltq
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x6040
movq %rax, -0x48(%rbp)
movl $0x0, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
cmpl -0x30(%rbp), %eax
jg 0x1d823
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rdi
callq 0x6040
movq %rax, %rdx
movq -0x48(%rbp), %rax
movslq -0x4c(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x1d7f3
movq -0x20(%rbp), %rdi
leaq 0x37d70(%rip), %rsi     # 0x5559e
callq 0x65c0
movq -0x28(%rbp), %rdi
leaq 0x37d60(%rip), %rsi     # 0x5559e
callq 0x65c0
movq -0xa8(%rbp), %rdi
movq -0x38(%rbp), %rsi
movq -0x48(%rbp), %rdx
movl -0x2c(%rbp), %ecx
movl -0x30(%rbp), %r8d
callq 0x33410
movl $0x1, -0x50(%rbp)
movl -0x50(%rbp), %eax
cmpl -0x30(%rbp), %eax
jg 0x1d9e5
movl $0x1, -0x54(%rbp)
movl -0x54(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jg 0x1d9d5
movq -0xb0(%rbp), %rdi
movl -0x54(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x6810
movq -0xa0(%rbp), %rdi
movb (%rax), %al
movb %al, -0x55(%rbp)
movl -0x50(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x6810
movb (%rax), %al
movb %al, -0x56(%rbp)
movq -0x38(%rbp), %rax
movl -0x50(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movl -0x54(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x5c(%rbp)
movsbl -0x55(%rbp), %eax
movsbl -0x56(%rbp), %ecx
cmpl %ecx, %eax
je 0x1d8ed
movl -0x5c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x5c(%rbp)
movq -0x38(%rbp), %rax
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movl -0x54(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
subl $0x1, %eax
movl %eax, -0x60(%rbp)
movq -0x38(%rbp), %rax
movl -0x50(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movl (%rax,%rcx,4), %eax
subl $0x1, %eax
movl %eax, -0x64(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x60(%rbp), %eax
jle 0x1d965
movl -0x5c(%rbp), %eax
cmpl -0x64(%rbp), %eax
jle 0x1d965
movl -0x5c(%rbp), %edx
movq -0x38(%rbp), %rax
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x48(%rbp), %rax
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movb $0x2a, (%rax,%rcx)
jmp 0x1d9c5
movl -0x60(%rbp), %eax
cmpl -0x64(%rbp), %eax
jl 0x1d999
movl -0x60(%rbp), %edx
movq -0x38(%rbp), %rax
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x48(%rbp), %rax
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movb $0x2d, (%rax,%rcx)
jmp 0x1d9c3
movl -0x64(%rbp), %edx
movq -0x38(%rbp), %rax
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x48(%rbp), %rax
movslq -0x50(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x54(%rbp), %rcx
movb $0x7c, (%rax,%rcx)
jmp 0x1d9c5
jmp 0x1d9c7
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x1d878
jmp 0x1d9d7
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x1d865
movl -0x30(%rbp), %eax
movl %eax, -0x68(%rbp)
movl -0x2c(%rbp), %eax
movl %eax, -0x6c(%rbp)
movb $0x1, %al
cmpl $0x0, -0x68(%rbp)
movb %al, -0xb9(%rbp)
jg 0x1da0c
cmpl $0x0, -0x6c(%rbp)
setg %al
movb %al, -0xb9(%rbp)
movb -0xb9(%rbp), %al
testb $0x1, %al
jne 0x1da1b
jmp 0x1db42
movq -0x48(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x6c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x2a, %eax
jne 0x1da91
movq -0xb0(%rbp), %rdi
movl -0x6c(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x6810
movb (%rax), %al
movq -0x20(%rbp), %rdi
movsbl %al, %esi
callq 0x62b0
movq -0xa0(%rbp), %rdi
movl -0x68(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x6810
movb (%rax), %al
movq -0x28(%rbp), %rdi
movsbl %al, %esi
callq 0x62b0
movl -0x68(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x68(%rbp)
movl -0x6c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x1db3d
movq -0x48(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x6c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x2d, %eax
jne 0x1dae6
movq -0xb0(%rbp), %rdi
movl -0x6c(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x6810
movb (%rax), %al
movq -0x20(%rbp), %rdi
movsbl %al, %esi
callq 0x62b0
movq -0x28(%rbp), %rdi
movl $0x2d, %esi
callq 0x62b0
movl -0x6c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x1db3b
movq -0x48(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x6c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x7c, %eax
jne 0x1db39
movq -0x20(%rbp), %rdi
movl $0x2d, %esi
callq 0x62b0
movq -0xa0(%rbp), %rdi
movl -0x68(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x6810
movb (%rax), %al
movq -0x28(%rbp), %rdi
movsbl %al, %esi
callq 0x62b0
movl -0x68(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0x1db3b
jmp 0x1db3d
jmp 0x1d9f1
movq -0x20(%rbp), %rdi
callq 0x63c0
movq %rax, -0x78(%rbp)
movq -0x20(%rbp), %rdi
callq 0x6270
movq %rax, -0x80(%rbp)
movq -0x78(%rbp), %rdi
movq -0x80(%rbp), %rsi
callq 0x334c0
movq -0x28(%rbp), %rdi
callq 0x63c0
movq %rax, -0x88(%rbp)
movq -0x28(%rbp), %rdi
callq 0x6270
movq %rax, -0x90(%rbp)
movq -0x88(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x334c0
movq -0x38(%rbp), %rax
movslq -0x30(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x2c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x94(%rbp)
movl $0x0, -0x98(%rbp)
movl -0x98(%rbp), %eax
cmpl -0x30(%rbp), %eax
jg 0x1dc37
movq -0x38(%rbp), %rax
movslq -0x98(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xc8(%rbp)
cmpq $0x0, %rax
je 0x1dbf7
movq -0xc8(%rbp), %rdi
movl $0x4, %esi
callq 0x6440
movq -0x48(%rbp), %rax
movslq -0x98(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xd0(%rbp)
cmpq $0x0, %rax
je 0x1dc24
movq -0xd0(%rbp), %rdi
movl $0x1, %esi
callq 0x6440
jmp 0x1dc26
movl -0x98(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x98(%rbp)
jmp 0x1dbbf
movq -0x38(%rbp), %rax
movq %rax, -0xd8(%rbp)
cmpq $0x0, %rax
je 0x1dc59
movq -0xd8(%rbp), %rdi
movl $0x8, %esi
callq 0x6440
movq -0x48(%rbp), %rax
movq %rax, -0xe0(%rbp)
cmpq $0x0, %rax
je 0x1dc7b
movq -0xe0(%rbp), %rdi
movl $0x8, %esi
callq 0x6440
movl -0x94(%rbp), %eax
addq $0xe0, %rsp
popq %rbp
retq
nopw (%rax,%rax)