// File: /workspace/github_cpp_makefile_star2_O3/JameyWoo[P]re2graph/algorithms.cpp
// Function: dfa2min(DFA)
DFA dfa2min(DFA dfa) {
    // 先分出 终止状态集 和 非终止状态集. 并添加到state2set中
    set<int> no_end, end;
    for (auto s : dfa.states) {
        if (count(dfa.end_states.begin(), dfa.end_states.end(), s)) {
            end.insert(s);
        } else {
            no_end.insert(s);
        }
    }
    vector<set<int>> state2set(dfa.state_cnt);  // 每个状态对应的集合
    for (auto s : no_end) {
        state2set[s] = no_end;
    }
    for (auto s : end) {
        state2set[s] = end;
    }

    // 集合的记录, 以set<int>为key, 方便查找
    map<set<int>, int> set_cnt;
    for (auto s : state2set) {  // 各个集合
        set_cnt[s] = 1;
    }
    int last = set_cnt.size();  // 初始时集合的数量

    while (true) {
        // ! 开始拆分集合
        bool flag = false;  //  标记是否可以划分集合, 如果可以, 则处理完当前划分后马上退出.
        for (auto one : set_cnt) {
            set<int> the_set = one.first;               // 当前准备拆分的集合
            for (auto c : dfa.chars) {                  // 遍历每个字符, 查找可以拆分的情况
                map<set<int>, vector<int>> next2state;  // 下一状态所属集合对当前状态的映射, 可根据这个映射划分集合
                set<int> empty_states;
                bool empty = false;
                for (auto state : the_set) {
                    if (dfa.jump_map[state].count(c) == 0) {
                        // ! 解决当一个状态输入c无法跳转的情况
                        empty = true;
                        empty_states.insert(state);
                    } else {
                        int next = dfa.jump_map[state][c];
                        next2state[state2set[next]].push_back(state);
                    }
                }
                if (next2state.size() > 1 || (empty && next2state.size() == 1)) {  // 考虑某条件下无法扩展的状态
                    for (auto next_states : next2state) {
                        set<int> new_set;  // 新集合
                        for (auto new_set_state : next_states.second) {
                            new_set.insert(new_set_state);
                        }
                        for (auto new_set_state : next_states.second) {
                            state2set[new_set_state] = new_set;
                        }
                    }
                    if (empty) {
                        for (auto s : empty_states) {
                            state2set[s] = empty_states;
                        }
                    }
                    flag = true;
                    break;
                }
                if (flag) break;
            }
            if (flag) break;
        }

        // ! 统计集合的数量, 和上一次进行比较
        set_cnt.clear();            // 清空, 重新统计.
        for (auto s : state2set) {  // 统计split之后集合个数
            set_cnt[s] = 1;
        }
        if (last == set_cnt.size()) break;  // 集合没有变化了, 说明不可再划分
        last = set_cnt.size();
    }

    // ! 合并旧状态为新状态
    DFA min_dfa;
    int new_state_id = 0;
    map<set<int>, int> set2id;
    for (auto one_set : set_cnt) {
        set2id[one_set.first] = new_state_id++;
    }
    vector<map<char, int>> new_jump(new_state_id);
    for (int from = 0; from < dfa.state_cnt; ++from) {
        for (auto m : dfa.jump_map[from]) {
            new_jump[set2id[state2set[from]]][m.first] = set2id[state2set[m.second]];
        }
    }
    min_dfa.jump_map = new_jump;

    min_dfa.char_cnt    = dfa.char_cnt;
    min_dfa.state_cnt   = new_state_id;
    min_dfa.start_state = 0;
    // 添加终止状态
    set<int> end_states_set;
    for (auto one_end_state : dfa.end_states) {
        end_states_set.insert(set2id[state2set[one_end_state]]);
    }
    for (auto s : end_states_set) {
        min_dfa.end_states.push_back(s);
    }
    min_dfa.end_state_cnt = min_dfa.end_states.size();
    min_dfa.chars         = dfa.chars;
    for (int i = 0; i < new_state_id; ++i) {
        min_dfa.states.push_back(i);
    }

    // 成功最小化, 查看各个状态所属的集合
    // for (int i = 0; i < dfa.state_cnt; ++i) {
    //     cout << i << ": ";
    //     for (auto s : state2set[i]) {
    //         cout << s << ' ';
    //     }
    //     cout << endl;
    // }
    return min_dfa;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x238, %rsp            # imm = 0x238
movq %rdi, 0x8(%rsp)
leaq 0x210(%rsp), %r12
xorl %eax, %eax
movl %eax, (%r12)
movq %rax, 0x8(%r12)
movq %r12, 0x10(%r12)
movq %r12, 0x18(%r12)
movq %rax, 0x20(%r12)
leaq 0x1e0(%rsp), %rcx
movl %eax, (%rcx)
movq %rax, 0x8(%rcx)
movq %rcx, 0x10(%rcx)
movq %rcx, 0x18(%rcx)
movq %rax, 0x20(%rcx)
movq 0x28(%rsi), %r15
movq %rsi, 0x18(%rsp)
movq 0x30(%rsi), %r13
cmpq %r13, %r15
je 0x746b
leaq 0x208(%rsp), %rbp
leaq 0x48(%rsp), %rbx
leaq 0x1d8(%rsp), %r14
movl (%r15), %eax
movl %eax, 0x48(%rsp)
movq 0x18(%rsp), %rdx
movq 0x40(%rdx), %rcx
movq 0x48(%rdx), %rdx
movq %rbp, %rdi
cmpq %rdx, %rcx
je 0x745a
xorl %esi, %esi
xorl %edi, %edi
cmpl %eax, (%rcx)
sete %dil
addq %rdi, %rsi
addq $0x4, %rcx
cmpq %rdx, %rcx
jne 0x743c
testq %rsi, %rsi
movq %r14, %rdi
cmoveq %rbp, %rdi
movq %rbx, %rsi
callq 0xffb0
addq $0x4, %r15
cmpq %r13, %r15
jne 0x741e
movq 0x18(%rsp), %r13
movslq 0x4(%r13), %rsi
leaq 0x20(%rsp), %rdi
leaq 0x48(%rsp), %rdx
callq 0xdaf4
movq 0x220(%rsp), %rbx
cmpq %r12, %rbx
je 0x74c1
leaq 0x208(%rsp), %r15
movslq 0x20(%rbx), %rax
leaq (%rax,%rax,2), %rdi
shlq $0x4, %rdi
addq 0x20(%rsp), %rdi
movq %r15, %rsi
callq 0xe72e
movq %rbx, %rdi
callq 0x2250
movq %rax, %rbx
cmpq %r12, %rax
jne 0x7498
movq 0x1f0(%rsp), %rbx
leaq 0x1e0(%rsp), %r14
cmpq %r14, %rbx
je 0x7507
leaq 0x1d8(%rsp), %r15
movslq 0x20(%rbx), %rax
leaq (%rax,%rax,2), %rdi
shlq $0x4, %rdi
addq 0x20(%rsp), %rdi
movq %r15, %rsi
callq 0xe72e
movq %rbx, %rdi
callq 0x2250
movq %rax, %rbx
cmpq %r14, %rax
jne 0x74de
leaq 0xd0(%rsp), %rax
movl $0x0, (%rax)
xorl %ecx, %ecx
movq %rcx, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
movq %rcx, 0x20(%rax)
movq 0x20(%rsp), %rbx
movq 0x28(%rsp), %r14
cmpq %r14, %rbx
je 0x7578
leaq 0x48(%rsp), %r15
leaq 0xc8(%rsp), %r12
movq %r15, %rdi
movq %rbx, %rsi
callq 0xe380
movq %r12, %rdi
movq %r15, %rsi
callq 0xd790
movl $0x1, (%rax)
movq %r15, %rdi
callq 0xe2d8
addq $0x30, %rbx
cmpq %r14, %rbx
jne 0x7543
movq 0xf0(%rsp), %rcx
movq %rcx, 0xc0(%rsp)
leaq 0x10(%r13), %rax
movq %rax, 0x128(%rsp)
leaq 0x48(%rsp), %r14
leaq 0x170(%rsp), %rbx
leaq 0x1a8(%rsp), %r15
leaq 0x44(%rsp), %r12
movq 0xe0(%rsp), %rcx
leaq 0xd0(%rsp), %rax
cmpq %rax, %rcx
je 0x797b
xorl %ebp, %ebp
movl %ebp, 0x10(%rsp)
leaq 0x20(%rcx), %rsi
movq %rcx, %rbp
movq %rbx, %rdi
callq 0xe380
movq %rbp, 0x130(%rsp)
movl 0x50(%rbp), %eax
movl %eax, 0x1a0(%rsp)
leaq 0x140(%rsp), %rdi
movq %rbx, %rsi
callq 0xe380
movq 0x10(%r13), %rax
movq 0x18(%r13), %rcx
movq %rcx, 0x138(%rsp)
cmpq %rcx, %rax
je 0x7933
movq %rax, 0x38(%rsp)
movb (%rax), %al
movb %al, 0x7(%rsp)
xorl %eax, %eax
movl %eax, 0x98(%rsp)
movq %rax, 0xa0(%rsp)
leaq 0x98(%rsp), %rcx
movq %rcx, 0xa8(%rsp)
movq %rcx, 0xb0(%rsp)
movq %rax, 0xb8(%rsp)
movl %eax, 0x100(%rsp)
movq %rax, 0x108(%rsp)
leaq 0x100(%rsp), %rcx
movq %rcx, 0x110(%rsp)
movq %rcx, 0x118(%rsp)
movq %rax, 0x120(%rsp)
movq 0x158(%rsp), %rbp
leaq 0x148(%rsp), %rcx
cmpq %rcx, %rbp
je 0x7771
movq %r13, %rbx
xorl %r13d, %r13d
movslq 0x20(%rbp), %rax
movl %eax, 0x48(%rsp)
movq 0x58(%rbx), %rcx
leaq (%rax,%rax,2), %rdx
shlq $0x4, %rdx
movq 0x10(%rcx,%rdx), %rax
testq %rax, %rax
je 0x76ec
leaq (%rcx,%rdx), %rdi
leaq (%rcx,%rdx), %rsi
addq $0x8, %rsi
movb 0x7(%rsp), %cl
movq %rsi, %rdx
xorl %r8d, %r8d
cmpb %cl, 0x20(%rax)
setl %r8b
cmovgeq %rax, %rdx
movq 0x10(%rax,%r8,8), %rax
testq %rax, %rax
jne 0x76ca
cmpq %rsi, %rdx
je 0x76ec
cmpb 0x20(%rdx), %cl
jge 0x7719
movb $0x1, %r13b
leaq 0xf8(%rsp), %rdi
movq %r14, %rsi
callq 0xffb0
movq %rbp, %rdi
callq 0x2250
movq %rax, %rbp
leaq 0x148(%rsp), %rax
cmpq %rax, %rbp
jne 0x7699
jmp 0x7767
leaq 0x7(%rsp), %rsi
callq 0xd800
movslq (%rax), %rax
leaq (%rax,%rax,2), %rsi
shlq $0x4, %rsi
addq 0x20(%rsp), %rsi
leaq 0x90(%rsp), %rdi
callq 0xdb8c
movq 0x8(%rax), %rsi
cmpq 0x10(%rax), %rsi
je 0x775a
movl 0x48(%rsp), %ecx
movl %ecx, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rax)
jmp 0x76ff
movq %rax, %rdi
movq %r14, %rdx
callq 0xef76
jmp 0x76ff
movq 0xb8(%rsp), %rax
jmp 0x7774
xorl %r13d, %r13d
cmpq $0x2, %rax
setae %cl
cmpq $0x1, %rax
sete %al
andb %r13b, %al
orb %cl, %al
je 0x7887
movq %r13, 0x10(%rsp)
movq 0xa8(%rsp), %rbp
leaq 0x98(%rsp), %rax
cmpq %rax, %rbp
je 0x788e
leaq 0x20(%rbp), %rsi
movq %r14, %rdi
callq 0xdbfc
movl $0x0, 0x1b0(%rsp)
xorl %ecx, %ecx
movq %rcx, 0x1b8(%rsp)
leaq 0x1b0(%rsp), %rax
movq %rax, 0x1c0(%rsp)
movq %rax, 0x1c8(%rsp)
movq %rcx, 0x1d0(%rsp)
movq 0x78(%rsp), %rbx
movq 0x80(%rsp), %r13
cmpq %r13, %rbx
je 0x7848
movl (%rbx), %eax
movl %eax, 0x44(%rsp)
movq %r15, %rdi
movq %r12, %rsi
callq 0xffb0
addq $0x4, %rbx
cmpq %r13, %rbx
jne 0x77fe
movq 0x78(%rsp), %rbx
movq 0x80(%rsp), %r13
cmpq %r13, %rbx
je 0x7848
movslq (%rbx), %rax
leaq (%rax,%rax,2), %rdi
shlq $0x4, %rdi
addq 0x20(%rsp), %rdi
movq %r15, %rsi
callq 0xe72e
addq $0x4, %rbx
jmp 0x7825
movq %r15, %rdi
callq 0xe2d8
movq 0x78(%rsp), %rdi
testq %rdi, %rdi
je 0x786a
movq 0x88(%rsp), %rsi
subq %rdi, %rsi
callq 0x2200
leaq 0x48(%rsp), %r14
movq %r14, %rdi
callq 0xe2d8
movq %rbp, %rdi
callq 0x2160
movq %rax, %rbp
jmp 0x779a
movl 0x10(%rsp), %r13d
jmp 0x78ec
movq 0x110(%rsp), %rbp
leaq 0x100(%rsp), %rax
cmpq %rax, %rbp
setne %al
movq 0x10(%rsp), %rcx
andb %al, %cl
movb $0x1, %r13b
cmpb $0x1, %cl
jne 0x78ec
movslq 0x20(%rbp), %rax
leaq (%rax,%rax,2), %rdi
shlq $0x4, %rdi
addq 0x20(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0xe72e
movq %rbp, %rdi
callq 0x2250
movq %rax, %rbp
leaq 0x100(%rsp), %rax
cmpq %rax, %rbp
jne 0x78b3
movb $0x1, %r13b
leaq 0xf8(%rsp), %rdi
callq 0xe2d8
leaq 0x90(%rsp), %rdi
callq 0xe9b4
testb $0x1, %r13b
movl %r13d, 0x10(%rsp)
jne 0x792e
movq 0x38(%rsp), %rax
incq %rax
cmpq 0x138(%rsp), %rax
movq 0x18(%rsp), %r13
jne 0x760f
jmp 0x7933
movq 0x18(%rsp), %r13
leaq 0x140(%rsp), %rdi
callq 0xe2d8
leaq 0x170(%rsp), %rbx
movq %rbx, %rdi
callq 0xe2d8
movl 0x10(%rsp), %ebp
testb $0x1, %bpl
movq 0x130(%rsp), %rdi
jne 0x797b
callq 0x2160
movq %rax, %rcx
leaq 0xd0(%rsp), %rax
cmpq %rax, %rcx
jne 0x75c1
leaq 0xc8(%rsp), %rdi
callq 0x1152e
movq 0x20(%rsp), %rbp
movq 0x28(%rsp), %rbx
cmpq %rbx, %rbp
je 0x79c6
movq %r14, %rdi
movq %rbp, %rsi
callq 0xe380
leaq 0xc8(%rsp), %rdi
movq %r14, %rsi
callq 0xd790
movl $0x1, (%rax)
movq %r14, %rdi
callq 0xe2d8
addq $0x30, %rbp
jmp 0x7992
movslq 0xc0(%rsp), %rax
movq 0xf0(%rsp), %rdx
movq %rdx, 0xc0(%rsp)
cmpq %rax, %rdx
leaq 0x170(%rsp), %rbx
jne 0x75a6
xorps %xmm0, %xmm0
movq 0x8(%rsp), %rax
movups %xmm0, 0x60(%rax)
movups %xmm0, 0x50(%rax)
movups %xmm0, 0x40(%rax)
movups %xmm0, 0x30(%rax)
movups %xmm0, 0x20(%rax)
movups %xmm0, 0x10(%rax)
leaq 0x178(%rsp), %rax
movl $0x0, (%rax)
xorl %r14d, %r14d
movq %r14, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
movq %r14, 0x20(%rax)
movq 0xe0(%rsp), %rbx
leaq 0xd0(%rsp), %rax
cmpq %rax, %rbx
je 0x7a99
xorl %r14d, %r14d
leaq 0x48(%rsp), %r15
leaq 0x170(%rsp), %r12
leaq 0x20(%rbx), %rsi
movq %r15, %rdi
callq 0xe380
movl 0x50(%rbx), %eax
movl %eax, 0x78(%rsp)
movq %r12, %rdi
movq %r15, %rsi
callq 0xd790
movl %r14d, (%rax)
incl %r14d
movq %r15, %rdi
callq 0xe2d8
movq %rbx, %rdi
callq 0x2160
movq %rax, %rbx
leaq 0xd0(%rsp), %rax
cmpq %rax, %rbx
jne 0x7a55
movq %r14, 0x10(%rsp)
movl %r14d, %esi
leaq 0x140(%rsp), %rdi
leaq 0x48(%rsp), %rdx
callq 0xdc36
movl 0x4(%r13), %eax
testl %eax, %eax
jle 0x7b75
xorl %edx, %edx
leaq 0x170(%rsp), %rbx
leaq 0x48(%rsp), %r15
movq 0x58(%r13), %rcx
movq %rdx, 0x38(%rsp)
leaq (%rdx,%rdx,2), %rbp
shlq $0x4, %rbp
leaq (%rcx,%rbp), %r13
addq $0x8, %r13
movq 0x10(%r13), %r12
cmpq %r13, %r12
je 0x7b5c
movq 0x20(%r12), %rax
movq %rax, 0x48(%rsp)
sarq $0x20, %rax
leaq (%rax,%rax,2), %rsi
shlq $0x4, %rsi
addq 0x20(%rsp), %rsi
movq %rbx, %rdi
callq 0xd790
movl (%rax), %r14d
movq 0x20(%rsp), %rsi
addq %rbp, %rsi
movq %rbx, %rdi
callq 0xd790
movslq (%rax), %rax
leaq (%rax,%rax,2), %rdi
shlq $0x4, %rdi
addq 0x140(%rsp), %rdi
movq %r15, %rsi
callq 0xd800
movl %r14d, (%rax)
movq %r12, %rdi
callq 0x2160
movq %rax, %r12
cmpq %r13, %rax
jne 0x7af0
movq 0x18(%rsp), %rax
movl 0x4(%rax), %eax
movq 0x38(%rsp), %rdx
incq %rdx
movslq %eax, %rcx
cmpq %rcx, %rdx
movq 0x18(%rsp), %r13
jl 0x7ace
movq 0x8(%rsp), %rbx
leaq 0x58(%rbx), %rdi
leaq 0x140(%rsp), %rsi
callq 0xd92a
movl (%r13), %eax
movl %eax, (%rbx)
movq 0x10(%rsp), %rbp
movl %ebp, 0x4(%rbx)
xorl %eax, %eax
movl %eax, 0x8(%rbx)
leaq 0x50(%rsp), %r12
movl %eax, (%r12)
movq %rax, 0x8(%r12)
movq %r12, 0x10(%r12)
movq %r12, 0x18(%r12)
movq %rax, 0x20(%r12)
movq 0x40(%r13), %r15
movq 0x48(%r13), %r13
cmpq %r13, %r15
je 0x7c60
leaq 0x170(%rsp), %rbx
leaq 0x48(%rsp), %r14
movslq (%r15), %rax
leaq (%rax,%rax,2), %rsi
shlq $0x4, %rsi
addq 0x20(%rsp), %rsi
movq %rbx, %rdi
callq 0xd790
movq %r14, %rdi
movq %rax, %rsi
callq 0xffb0
addq $0x4, %r15
cmpq %r13, %r15
jne 0x7bd9
movq 0x60(%rsp), %rbx
cmpq %r12, %rbx
je 0x7c60
movq 0x8(%rsp), %rax
leaq 0x40(%rax), %r14
leaq 0x90(%rsp), %r15
movl 0x20(%rbx), %eax
movl %eax, 0x90(%rsp)
movq 0x8(%rsp), %rcx
movq 0x48(%rcx), %rsi
cmpq 0x50(%rcx), %rsi
je 0x7c45
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x48(%rcx)
jmp 0x7c50
movq %r14, %rdi
movq %r15, %rdx
callq 0xef76
movq %rbx, %rdi
callq 0x2250
movq %rax, %rbx
cmpq %r12, %rax
jne 0x7c20
movq 0x8(%rsp), %r15
leaq 0x10(%r15), %rdi
movq 0x48(%r15), %rax
subq 0x40(%r15), %rax
shrq $0x2, %rax
movl %eax, 0xc(%r15)
movq 0x128(%rsp), %rsi
callq 0xd866
movl $0x0, 0x90(%rsp)
testl %ebp, %ebp
jle 0x7cd8
leaq 0x28(%r15), %rbx
xorl %eax, %eax
leaq 0x90(%rsp), %r14
movq 0x30(%r15), %rsi
cmpq 0x38(%r15), %rsi
je 0x7cb9
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x30(%r15)
jmp 0x7cc4
movq %rbx, %rdi
movq %r14, %rdx
callq 0xef76
movl 0x90(%rsp), %eax
incl %eax
movl %eax, 0x90(%rsp)
cmpl %ebp, %eax
jl 0x7ca3
leaq 0x48(%rsp), %rdi
callq 0xe2d8
leaq 0x140(%rsp), %rdi
callq 0x4484
leaq 0x170(%rsp), %rdi
callq 0xe660
leaq 0xc8(%rsp), %rdi
callq 0xe660
leaq 0x20(%rsp), %rdi
callq 0xdaac
leaq 0x1d8(%rsp), %rdi
callq 0xe2d8
leaq 0x208(%rsp), %rdi
callq 0xe2d8
movq %r15, %rax
addq $0x238, %rsp            # imm = 0x238
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x7d62
jmp 0x7da6
jmp 0x7d5d
jmp 0x7d7f
jmp 0x7d62
jmp 0x7d62
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0xe2d8
jmp 0x7db6
movq %rax, %rbx
jmp 0x7db6
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0xe2d8
jmp 0x7da9
jmp 0x7d99
jmp 0x7d91
jmp 0x7d77
movq %rax, %rbx
jmp 0x7e54
movq %rax, %rbx
jmp 0x7e5e
jmp 0x7d91
movq %rax, %rbx
jmp 0x7e3a
movq %rax, %rbx
jmp 0x7e47
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
jmp 0x7e42
movq %rax, %rbx
leaq 0x140(%rsp), %rdi
callq 0x4484
movq 0x8(%rsp), %r14
leaq 0x170(%rsp), %rdi
callq 0xe660
movq %r14, %rdi
callq 0x3bc8
jmp 0x7e47
jmp 0x7dd8
jmp 0x7dd8
jmp 0x7dd8
movq %rax, %rbx
jmp 0x7e13
jmp 0x7ddf
movq %rax, %rbx
leaq 0x1a8(%rsp), %rdi
callq 0xe2d8
movq 0x78(%rsp), %rdi
testq %rdi, %rdi
je 0x7e09
movq 0x88(%rsp), %rsi
subq %rdi, %rsi
callq 0x2200
leaq 0x48(%rsp), %rdi
callq 0xe2d8
leaq 0xf8(%rsp), %rdi
callq 0xe2d8
leaq 0x90(%rsp), %rdi
callq 0xe9b4
leaq 0x140(%rsp), %rdi
callq 0xe2d8
leaq 0x170(%rsp), %rdi
callq 0xe2d8
leaq 0xc8(%rsp), %rdi
callq 0xe660
leaq 0x20(%rsp), %rdi
callq 0xdaac
leaq 0x1d8(%rsp), %rdi
callq 0xe2d8
leaq 0x208(%rsp), %rdi
callq 0xe2d8
movq %rbx, %rdi
callq 0x2350