// File: /workspace/github_cpp_makefile_star2_O2/fpavetic[P]lcskpp/lcskpp.cpp
// Function: get_matches(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, int, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int>>>*)
static void get_matches(
    const string& a, const string& b,
    const int k, vector<pair<int, int> >* matches) {
  assert(matches != NULL);
  matches->clear();

  vector<char> aid;
  int alphabet_size;
  prepare_alphabet(a, b, aid, alphabet_size);

  // We assume: alphabet_size ** k < 2 ** 64,
  // in the case this does not hold, the entire
  // get_matches function probably has to be
  // reimplemented using non-perfect hashing or
  // suffix arrays.
  if (k * log(alphabet_size) >= 64 * log(2)) {
    fprintf(stderr, "We assume that alphabet_size ** k <\
2 ** 64.\nPlease see lcskpp.cpp for more information.");
    exit(1);
  }

  typedef unordered_multimap<uint64_t, int> MatchIndexType;
  unique_ptr<MatchIndexType> match_index =
    unique_ptr<MatchIndexType>(new MatchIndexType());

  uint64_t hash_mod = 1;
  for (int i = 0; i < k; ++i) hash_mod *= alphabet_size;

  if (alphabet_size == 4) {
    assert(hash_mod == (1LL<<(2*k)));
  }

  uint64_t rolling_hash = 0;
  for (int i = 0; i < a.size(); ++i) {
    rolling_hash = rolling_hash * alphabet_size + aid[a[i]];
    rolling_hash %= hash_mod;

    if (i+1 >= k) {
      match_index->insert(
        MatchIndexType::value_type(rolling_hash, i-k+1));
    }
  }

  rolling_hash = 0;
  for (int i = 0; i < b.size(); ++i) {
    rolling_hash = rolling_hash * alphabet_size + aid[b[i]];
    rolling_hash %= hash_mod;

    if (i+1 >= k) {
      auto positions_in_a = match_index->equal_range(rolling_hash);
      for (auto it = positions_in_a.first; 
           it != positions_in_a.second; ++it) {
        matches->push_back(make_pair(it->second, i-k+1));
      }
    }
  }

  sort(matches->begin(), matches->end());
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdx, (%rsp)
testq %rcx, %rcx
je 0x2f6f
movq %rcx, %rbx
movq %rsi, %r14
movq %rdi, %r12
movq (%rcx), %rax
cmpq %rax, 0x8(%rcx)
je 0x2cdc
movq %rax, 0x8(%rbx)
andq $0x0, 0x30(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0x20(%rsp)
leaq 0x10(%rsp), %rdx
movb $-0x1, (%rdx)
leaq 0x50(%rsp), %rdi
leaq 0x8(%rsp), %rcx
movl $0x100, %esi            # imm = 0x100
callq 0x3c84
leaq 0x20(%rsp), %rdi
leaq 0x50(%rsp), %r13
movq %r13, %rsi
callq 0x3d54
movq %r13, %rdi
callq 0x3cf8
xorl %r13d, %r13d
xorl %eax, %eax
cmpq 0x8(%r12), %rax
jae 0x2d52
movq (%r12), %rcx
movsbq (%rcx,%rax), %rcx
movq 0x20(%rsp), %rdx
cmpb $-0x1, (%rdx,%rcx)
jne 0x2d4d
movb %r13b, (%rdx,%rcx)
leal 0x1(%r13), %ecx
movl %ecx, %r13d
incq %rax
jmp 0x2d27
xorl %eax, %eax
cmpq 0x8(%r14), %rax
jae 0x2d7d
movq (%r14), %rcx
movsbq (%rcx,%rax), %rcx
movq 0x20(%rsp), %rdx
cmpb $-0x1, (%rdx,%rcx)
jne 0x2d78
movb %r13b, (%rdx,%rcx)
leal 0x1(%r13), %ecx
movl %ecx, %r13d
incq %rax
jmp 0x2d54
cvtsi2sdl (%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movl %r13d, %edi
callq 0x3c61
mulsd 0x18(%rsp), %xmm0
ucomisd 0x34ba(%rip), %xmm0     # 0x6258
jae 0x2f88
pushq $0x38
popq %rdi
callq 0x2140
xorpd %xmm0, %xmm0
movapd %xmm0, 0x20(%rax)
movq %rax, %rcx
addq $0x30, %rcx
movq %rcx, (%rax)
movq $0x1, 0x8(%rax)
movupd %xmm0, 0x10(%rax)
movl $0x3f800000, 0x20(%rax) # imm = 0x3F800000
movupd %xmm0, 0x28(%rax)
movq %rax, 0x10(%rsp)
movslq %r13d, %rdi
xorl %eax, %eax
movq (%rsp), %rcx
testl %ecx, %ecx
cmovgl %ecx, %eax
pushq $0x1
popq %r8
subl $0x1, %eax
jb 0x2dfa
imulq %rdi, %r8
jmp 0x2def
movq %r14, 0x40(%rsp)
cmpl $0x4, %r13d
jne 0x2e1b
movq (%rsp), %rax
leal (%rax,%rax), %ecx
pushq $0x1
popq %rax
shlq %cl, %rax
cmpq %rax, %r8
jne 0x2fac
pushq $0x1
popq %r14
subl (%rsp), %r14d
xorl %ebp, %ebp
leaq 0x50(%rsp), %r13
xorl %r15d, %r15d
movq %rdi, 0x18(%rsp)
movq %r8, 0x48(%rsp)
cmpq %r15, 0x8(%r12)
jbe 0x2e97
imulq %rdi, %rbp
movq (%r12), %rax
movsbq (%rax,%r15), %rax
movq 0x20(%rsp), %rcx
movsbq (%rcx,%rax), %rax
addq %rbp, %rax
xorl %edx, %edx
divq %r8
movq %rdx, %rbp
movq %rdx, 0x8(%rsp)
leal 0x1(%r15), %eax
cmpl (%rsp), %eax
jl 0x2e92
movq 0x10(%rsp), %rdi
leal (%r14,%r15), %eax
movq %rbp, 0x50(%rsp)
movl %eax, 0x58(%rsp)
movq %r13, %rsi
callq 0x3da6
movq 0x18(%rsp), %rdi
movq 0x48(%rsp), %r8
incq %r15
jmp 0x2e37
leaq 0x8(%rsp), %rax
andq $0x0, (%rax)
xorl %r15d, %r15d
leaq 0x50(%rsp), %r13
movq 0x40(%rsp), %rsi
cmpq %r15, 0x8(%rsi)
jbe 0x2f40
movq %r15, %r14
movq 0x8(%rsp), %rcx
imulq %rdi, %rcx
movq (%rsi), %rax
movsbq (%rax,%r15), %rax
movq 0x20(%rsp), %rdx
movsbq (%rdx,%rax), %rax
addq %rcx, %rax
xorl %edx, %edx
divq %r8
movq %rdx, 0x8(%rsp)
incq %r15
cmpl (%rsp), %r15d
jl 0x2ead
movq 0x10(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x41c8
movq %rax, %rbp
movq %rdx, %r12
subl (%rsp), %r14d
incl %r14d
shlq $0x20, %r14
cmpq %r12, %rbp
je 0x2f2c
movl 0x10(%rbp), %eax
orq %r14, %rax
movq %rax, 0x50(%rsp)
movq %rbx, %rdi
movq %r13, %rsi
callq 0x4220
movq (%rbp), %rbp
jmp 0x2f0b
movq 0x40(%rsp), %rsi
movq 0x18(%rsp), %rdi
movq 0x48(%rsp), %r8
jmp 0x2ead
movq (%rbx), %rdi
movq 0x8(%rbx), %rsi
callq 0x437b
leaq 0x10(%rsp), %rdi
callq 0x3c6a
leaq 0x20(%rsp), %rdi
callq 0x3cf8
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x32ea(%rip), %rdi      # 0x6260
leaq 0x3133(%rip), %rsi      # 0x60b0
leaq 0x32ec(%rip), %rcx      # 0x6270
pushq $0x36
jmp 0x2fc3
movq 0x7049(%rip), %rax      # 0x9fd8
movq (%rax), %rcx
leaq 0x332d(%rip), %rdi      # 0x62c6
pushq $0x57
popq %rsi
pushq $0x1
popq %rdx
callq 0x2200
pushq $0x1
popq %rdi
callq 0x2160
leaq 0x336b(%rip), %rdi      # 0x631e
leaq 0x30f6(%rip), %rsi      # 0x60b0
leaq 0x32af(%rip), %rcx      # 0x6270
pushq $0x50
popq %rdx
callq 0x20c0
jmp 0x2fd6
jmp 0x2fcd
movq %rax, %rbx
jmp 0x2fe3
jmp 0x2fd6
jmp 0x2fd6
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x3c6a
leaq 0x20(%rsp), %rdi
callq 0x3cf8
movq %rbx, %rdi
callq 0x21f0