// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %r8, 0x8(%rsp)
movq %rcx, (%rsp)
movq %rdx, %r13
movq %rsi, %rbp
movq %rdi, 0x30(%rsp)
movq 0x8(%rsi), %r12
movq 0x8(%rdx), %r15
movq %r15, %rax
shlq $0x20, %rax
movabsq $0x100000000, %r14      # imm = 0x100000000
movq %rax, 0x40(%rsp)
addq %r14, %rax
movq %rax, %rdi
sarq $0x1d, %rdi
testq %rax, %rax
pushq $-0x1
popq %rax
cmovsq %rax, %rdi
movq %rdi, 0x28(%rsp)
callq 0x5030
movq %rax, %rbx
movq %r12, 0x10(%rsp)
movq %r12, %rax
shlq $0x20, %rax
movq %rax, 0x38(%rsp)
addq %rax, %r14
movq %r14, %r12
sarq $0x1e, %r12
testq %r14, %r14
pushq $-0x1
popq %rax
cmovsq %rax, %r12
movq %r15, 0x18(%rsp)
movslq %r15d, %rax
movq %rax, 0x20(%rsp)
xorl %r15d, %r15d
cmpq 0x20(%rsp), %r15
jg 0xeb2c
movq %r12, %rdi
callq 0x5030
movq %rax, (%rbx,%r15,8)
incq %r15
jmp 0xeb14
movq 0x28(%rsp), %rdi
callq 0x5030
movq %rax, %r15
sarq $0x20, %r14
xorl %r12d, %r12d
cmpq 0x20(%rsp), %r12
jg 0xeb58
movq %r14, %rdi
callq 0x5030
movq %rax, (%r15,%r12,8)
incq %r12
jmp 0xeb40
leaq 0x13a4b(%rip), %r14     # 0x225aa
movq (%rsp), %rdi
movq %r14, %rsi
callq 0x55b0
movq 0x8(%rsp), %rdi
movq %r14, %rsi
callq 0x55b0
movq 0x30(%rsp), %rdi
movq %rbx, %rsi
movq %r15, %rdx
movq 0x10(%rsp), %r14
movl %r14d, %ecx
movq 0x18(%rsp), %r12
movl %r12d, %r8d
callq 0x19e7a
xorl %eax, %eax
testl %r14d, %r14d
movl $0x0, %ecx
cmovgl %r14d, %ecx
testl %r12d, %r12d
cmovgl %r12d, %eax
incl %eax
pushq $0x1
popq %rdx
cmpq %rax, %rdx
je 0xec36
xorl %esi, %esi
cmpq %rsi, %rcx
je 0xec2e
movq (%rbp), %rdi
movb (%rdi,%rsi), %dil
movq (%r13), %r8
xorl %r9d, %r9d
cmpb -0x1(%r8,%rdx), %dil
setne %r9b
movq -0x8(%rbx,%rdx,8), %r8
movq (%rbx,%rdx,8), %rdi
movl (%r8,%rsi,4), %r10d
subl %r9d, %r10d
movl 0x4(%r8,%rsi,4), %r8d
movl (%rdi,%rsi,4), %r9d
cmpl %r9d, %r10d
jl 0xec03
cmpl %r8d, %r10d
jl 0xec03
movl %r10d, 0x4(%rdi,%rsi,4)
movb $0x2a, %dil
jmp 0xec20
cmpl %r8d, %r9d
jge 0xec15
decl %r8d
movl %r8d, 0x4(%rdi,%rsi,4)
movb $0x7c, %dil
jmp 0xec20
decl %r9d
movl %r9d, 0x4(%rdi,%rsi,4)
movb $0x2d, %dil
movq (%r15,%rdx,8), %r8
movb %dil, 0x1(%r8,%rsi)
incq %rsi
jmp 0xebb9
incq %rdx
jmp 0xebb2
testl %r12d, %r12d
setg %cl
testl %r14d, %r14d
setg %al
orb %cl, %al
movq %r12, 0x18(%rsp)
movslq %r12d, %r12
movq %r14, 0x10(%rsp)
movslq %r14d, %r14
testb %al, %al
je 0xece6
movq (%r15,%r12,8), %rcx
movzbl (%rcx,%r14), %ecx
cmpl $0x7c, %ecx
je 0xec98
cmpl $0x2d, %ecx
je 0xecb7
cmpl $0x2a, %ecx
jne 0xec54
movq (%rbp), %rax
movsbl -0x1(%rax,%r14), %esi
decq %r14
movq (%rsp), %rdi
callq 0x52a0
movq (%r13), %rax
movb -0x1(%rax,%r12), %al
decq %r12
jmp 0xecd4
movq (%rsp), %rdi
pushq $0x2d
popq %rsi
callq 0x52a0
movq (%r13), %rax
movb -0x1(%rax,%r12), %al
decq %r12
movq 0x10(%rsp), %r14
jmp 0xecd4
movq (%rbp), %rax
movsbl -0x1(%rax,%r14), %esi
decq %r14
movq (%rsp), %rdi
callq 0x52a0
movb $0x2d, %al
movq 0x18(%rsp), %r12
movsbl %al, %esi
movq 0x8(%rsp), %rdi
callq 0x52a0
jmp 0xec36
movq (%rsp), %rax
movq (%rax), %rdi
movq 0x8(%rax), %rsi
addq %rdi, %rsi
callq 0x1d88d
movq 0x8(%rsp), %rax
movq (%rax), %rdi
movq 0x8(%rax), %rsi
addq %rdi, %rsi
callq 0x1d88d
movq 0x40(%rsp), %rax
sarq $0x1d, %rax
movq (%rbx,%rax), %rax
movq 0x38(%rsp), %rcx
sarq $0x1e, %rcx
movl (%rax,%rcx), %ebp
xorl %r13d, %r13d
pushq $0x4
popq %r14
pushq $0x1
popq %r12
cmpq 0x20(%rsp), %r13
jg 0xed55
movq (%rbx,%r13,8), %rdi
movq %r14, %rsi
callq 0x5310
movq (%r15,%r13,8), %rdi
movq %r12, %rsi
callq 0x5310
incq %r13
jmp 0xed31
pushq $0x8
popq %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x5310
movq %r15, %rdi
movq %r14, %rsi
callq 0x5310
movl %ebp, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq