// File: huntzhan[P]SAM-PNG/solution.cc
// Function: AddSymbolToSAM(State*, State*, char)
State *AddSymbolToSAM(State *start, State *last, char c) {
  auto cur = new State;
  cur->set_maxlen(last->maxlen() + 1);
  cur->set_first_endpos(last->first_endpos() + 1);

  auto p = last;
  while (p && !p->has_trans(c)) {
    p->set_trans(c, cur);
    p = p->link();
  }

  if (p == nullptr) {
    cur->set_link(start);
    cur->set_minlen(1);
    return cur;
  }

  auto q = p->trans(c);
  if (p->maxlen() + 1 == q->maxlen()) {
    cur->set_link(q);
    cur->set_minlen(q->maxlen() + 1);
  } else {
    auto sq = new State;
    sq->set_maxlen(p->maxlen() + 1);
    sq->set_trans(q->trans());
    sq->set_first_endpos(q->first_endpos());
    
    while (p && p->has_trans(c) && p->trans(c) == q) {
      p->set_trans(c, sq);
      p = p->link();
    }

    sq->set_link(q->link());
    sq->set_minlen(sq->link()->maxlen() + 1);

    q->set_link(sq);
    q->set_minlen(sq->maxlen() + 1);

    cur->set_link(sq);
    cur->set_minlen(sq->maxlen() + 1);
  }

  return cur;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movb %dl, %al
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movb %al, -0x19(%rbp)
movl $0x58, %edi
callq 0x2150
movq %rax, %rdi
movq %rdi, -0xa0(%rbp)
callq 0x3680
movq -0xa0(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x18(%rbp), %rdi
callq 0x36f0
movq -0x98(%rbp), %rdi
movl %eax, %esi
addl $0x1, %esi
callq 0x36d0
movq -0x28(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x18(%rbp), %rdi
callq 0x3720
movq -0x90(%rbp), %rdi
movl %eax, %esi
addl $0x1, %esi
callq 0x3700
movq -0x18(%rbp), %rax
movq %rax, -0x30(%rbp)
xorl %eax, %eax
cmpq $0x0, -0x30(%rbp)
movb %al, -0xa1(%rbp)
je 0x26a2
movq -0x30(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x3740
xorb $-0x1, %al
movb %al, -0xa1(%rbp)
movb -0xa1(%rbp), %al
testb $0x1, %al
jne 0x26ae
jmp 0x26d0
movq -0x30(%rbp), %rdi
movb -0x19(%rbp), %al
movq -0x28(%rbp), %rdx
movsbl %al, %esi
callq 0x3780
movq -0x30(%rbp), %rdi
callq 0x37c0
movq %rax, -0x30(%rbp)
jmp 0x267e
cmpq $0x0, -0x30(%rbp)
jne 0x26ff
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x37e0
movq -0x28(%rbp), %rdi
movl $0x1, %esi
callq 0x3800
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x2963
movq -0x30(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x3820
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rdi
callq 0x36f0
addl $0x1, %eax
movl %eax, -0xa8(%rbp)
movq -0x38(%rbp), %rdi
callq 0x36f0
movl %eax, %ecx
movl -0xa8(%rbp), %eax
cmpl %ecx, %eax
jne 0x276e
movq -0x28(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x37e0
movq -0x28(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x38(%rbp), %rdi
callq 0x36f0
movq -0xb0(%rbp), %rdi
movl %eax, %esi
addl $0x1, %esi
callq 0x3800
jmp 0x295b
movl $0x58, %edi
callq 0x2150
movq %rax, %rdi
movq %rdi, -0xd0(%rbp)
callq 0x3680
movq -0xd0(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0x30(%rbp), %rdi
callq 0x36f0
movq -0xc8(%rbp), %rdi
movl %eax, %esi
incl %esi
callq 0x36d0
movq -0x40(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0x38(%rbp), %rsi
leaq -0x78(%rbp), %rdi
movq %rdi, -0xb8(%rbp)
callq 0x3880
movq -0xc0(%rbp), %rdi
movq -0xb8(%rbp), %rsi
callq 0x3850
jmp 0x27ea
leaq -0x78(%rbp), %rdi
callq 0x38b0
movq -0x40(%rbp), %rax
movq %rax, -0xd8(%rbp)
movq -0x38(%rbp), %rdi
callq 0x3720
movq -0xd8(%rbp), %rdi
movl %eax, %esi
callq 0x3700
xorl %eax, %eax
cmpq $0x0, -0x30(%rbp)
movb %al, -0xd9(%rbp)
je 0x285c
movq -0x30(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x3740
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0xd9(%rbp)
jne 0x2842
jmp 0x285c
movq -0x30(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x3820
cmpq -0x38(%rbp), %rax
sete %al
movb %al, -0xd9(%rbp)
movb -0xd9(%rbp), %al
testb $0x1, %al
jne 0x2868
jmp 0x28a7
movq -0x30(%rbp), %rdi
movb -0x19(%rbp), %al
movq -0x40(%rbp), %rdx
movsbl %al, %esi
callq 0x3780
movq -0x30(%rbp), %rdi
callq 0x37c0
movq %rax, -0x30(%rbp)
jmp 0x2815
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x38b0
jmp 0x2970
movq -0x40(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x38(%rbp), %rdi
callq 0x37c0
movq -0x100(%rbp), %rdi
movq %rax, %rsi
callq 0x37e0
movq -0x40(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq -0x40(%rbp), %rdi
callq 0x37c0
movq %rax, %rdi
callq 0x36f0
movq -0xf8(%rbp), %rdi
movl %eax, %esi
addl $0x1, %esi
callq 0x3800
movq -0x38(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x37e0
movq -0x38(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0x40(%rbp), %rdi
callq 0x36f0
movq -0xf0(%rbp), %rdi
movl %eax, %esi
addl $0x1, %esi
callq 0x3800
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x37e0
movq -0x28(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0x40(%rbp), %rdi
callq 0x36f0
movq -0xe8(%rbp), %rdi
movl %eax, %esi
addl $0x1, %esi
callq 0x3800
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
movq -0x80(%rbp), %rdi
callq 0x22b0
nopl (%rax)