// File: /workspace/github_cpp_makefile_star2_O1/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, 0x20(%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, 0x10(%rsp)
movq 0x30(%rsi), %r13
cmpq %r13, %r15
je 0x74b8
leaq 0x208(%rsp), %rbp
leaq 0x50(%rsp), %rbx
leaq 0x1d8(%rsp), %r14
movl (%r15), %eax
movl %eax, 0x50(%rsp)
movq 0x10(%rsp), %rdx
movq 0x40(%rdx), %rcx
movq 0x48(%rdx), %rdx
movq %rbp, %rdi
cmpq %rdx, %rcx
je 0x74a7
xorl %esi, %esi
xorl %edi, %edi
cmpl %eax, (%rcx)
sete %dil
addq %rdi, %rsi
addq $0x4, %rcx
cmpq %rdx, %rcx
jne 0x7489
testq %rsi, %rsi
movq %r14, %rdi
cmoveq %rbp, %rdi
movq %rbx, %rsi
callq 0xffc0
addq $0x4, %r15
cmpq %r13, %r15
jne 0x746b
movq 0x10(%rsp), %rax
movslq 0x4(%rax), %rsi
leaq 0x28(%rsp), %rdi
leaq 0x50(%rsp), %rdx
callq 0xdb34
movq 0x220(%rsp), %rbx
cmpq %r12, %rbx
je 0x750e
leaq 0x208(%rsp), %r15
movslq 0x20(%rbx), %rax
leaq (%rax,%rax,2), %rdi
shlq $0x4, %rdi
addq 0x28(%rsp), %rdi
movq %r15, %rsi
callq 0xe73a
movq %rbx, %rdi
callq 0x2250
movq %rax, %rbx
cmpq %r12, %rax
jne 0x74e5
movq 0x1f0(%rsp), %rbx
leaq 0x1e0(%rsp), %r14
cmpq %r14, %rbx
je 0x7554
leaq 0x1d8(%rsp), %r15
movslq 0x20(%rbx), %rax
leaq (%rax,%rax,2), %rdi
shlq $0x4, %rdi
addq 0x28(%rsp), %rdi
movq %r15, %rsi
callq 0xe73a
movq %rbx, %rdi
callq 0x2250
movq %rax, %rbx
cmpq %r14, %rax
jne 0x752b
leaq 0xd8(%rsp), %rcx
movl $0x0, (%rcx)
xorl %eax, %eax
movq %rax, 0x8(%rcx)
movq %rcx, 0x10(%rcx)
movq %rcx, 0x18(%rcx)
movq %rax, 0x20(%rcx)
movq 0x28(%rsp), %rbx
movq 0x30(%rsp), %r14
cmpq %r14, %rbx
je 0x75bd
leaq 0x50(%rsp), %r15
leaq 0xd0(%rsp), %r12
movq %r15, %rdi
movq %rbx, %rsi
callq 0xe39a
movq %r12, %rdi
movq %r15, %rsi
callq 0xd80a
movl $0x1, (%rax)
movq %r15, %rdi
callq 0xe2fa
addq $0x30, %rbx
cmpq %r14, %rbx
jne 0x7590
leaq 0xd0(%rsp), %rax
movl 0x28(%rax), %eax
movq %rax, 0xc8(%rsp)
leaq 0x148(%rsp), %r12
leaq 0x50(%rsp), %rbx
leaq 0x170(%rsp), %r13
leaq 0x1a8(%rsp), %rbp
leaq 0x4c(%rsp), %r15
movq 0xe8(%rsp), %rcx
leaq 0xd8(%rsp), %rax
cmpq %rax, %rcx
je 0x79dd
xorl %r14d, %r14d
leaq 0x20(%rcx), %rsi
movq %r13, %rdi
movq %rcx, %r13
callq 0xe39a
movq %r13, 0x130(%rsp)
movl 0x50(%r13), %eax
movl %eax, 0x1a0(%rsp)
leaq 0x140(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0xe39a
movq 0x10(%rsp), %rcx
movq 0x10(%rcx), %rax
movq 0x18(%rcx), %rcx
movq %rcx, 0x138(%rsp)
cmpq %rcx, %rax
je 0x7999
movl %r14d, 0x18(%rsp)
movq %rax, 0x40(%rsp)
movb (%rax), %al
movb %al, 0xf(%rsp)
xorl %r14d, %r14d
movl %r14d, 0xa0(%rsp)
movq %r14, 0xa8(%rsp)
leaq 0xa0(%rsp), %rax
movq %rax, 0xb0(%rsp)
movq %rax, 0xb8(%rsp)
movq %r14, 0xc0(%rsp)
movl %r14d, 0x108(%rsp)
movq %r14, 0x110(%rsp)
leaq 0x108(%rsp), %rax
movq %rax, 0x118(%rsp)
movq %rax, 0x120(%rsp)
movq %r14, 0x128(%rsp)
movq 0x158(%rsp), %r13
cmpq %r12, %r13
je 0x77cd
xorl %r14d, %r14d
movslq 0x20(%r13), %rax
movl %eax, 0x50(%rsp)
movq 0x10(%rsp), %rcx
movq 0x58(%rcx), %rdi
leaq (%rax,%rax,2), %rax
shlq $0x4, %rax
leaq (%rdi,%rax), %rcx
addq $0x8, %rcx
movq 0x8(%rcx), %rsi
movq %rcx, %rdx
testq %rsi, %rsi
je 0x7738
movb 0xf(%rsp), %r8b
movq %rcx, %rdx
xorl %r9d, %r9d
cmpb %r8b, 0x20(%rsi)
setl %r9b
cmovgeq %rsi, %rdx
movq 0x10(%rsi,%r9,8), %rsi
testq %rsi, %rsi
jne 0x771f
movq %rcx, %rsi
cmpq %rcx, %rdx
je 0x7750
movb 0xf(%rsp), %sil
cmpb 0x20(%rdx), %sil
cmovlq %rcx, %rdx
movq %rdx, %rsi
cmpq %rcx, %rsi
je 0x7799
addq %rax, %rdi
leaq 0xf(%rsp), %rsi
callq 0xd87a
movslq (%rax), %rax
leaq (%rax,%rax,2), %rsi
shlq $0x4, %rsi
addq 0x28(%rsp), %rsi
leaq 0x98(%rsp), %rdi
callq 0xdbd0
movq 0x8(%rax), %rsi
cmpq 0x10(%rax), %rsi
je 0x77ae
movl 0x50(%rsp), %ecx
movl %ecx, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rax)
jmp 0x77b9
movb $0x1, %r14b
leaq 0x100(%rsp), %rdi
movq %rbx, %rsi
callq 0xffc0
jmp 0x77b9
movq %rax, %rdi
movq %rbx, %rdx
callq 0xef7e
movq %r13, %rdi
callq 0x2250
movq %rax, %r13
cmpq %r12, %rax
jne 0x76ea
movq 0xc0(%rsp), %rax
cmpq $0x2, %rax
setae %cl
cmpq $0x1, %rax
sete %al
andb %r14b, %al
orb %cl, %al
je 0x795e
movq %r14, 0x18(%rsp)
movq 0xb0(%rsp), %r13
leaq 0xa0(%rsp), %rax
cmpq %rax, %r13
je 0x78fe
leaq 0x20(%r13), %rsi
movq %rbx, %rdi
callq 0xdc40
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 0x80(%rsp), %r14
movq 0x88(%rsp), %r12
cmpq %r12, %r14
je 0x787a
movl (%r14), %eax
movl %eax, 0x4c(%rsp)
movq %rbp, %rdi
movq %r15, %rsi
callq 0xffc0
addq $0x4, %r14
jmp 0x785d
movq 0x80(%rsp), %r14
movq 0x88(%rsp), %r12
cmpq %r12, %r14
je 0x78ad
movslq (%r14), %rax
leaq (%rax,%rax,2), %rdi
shlq $0x4, %rdi
addq 0x28(%rsp), %rdi
movq %rbp, %rsi
callq 0xe73a
addq $0x4, %r14
jmp 0x788a
movq %rbp, %rdi
callq 0xe2fa
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x78d2
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x2200
movq %rbx, %rdi
callq 0xe2fa
movq %r13, %rdi
callq 0x2160
movq %rax, %r13
leaq 0xa0(%rsp), %rax
cmpq %rax, %r13
leaq 0x148(%rsp), %r12
jne 0x780c
movq 0x118(%rsp), %r13
leaq 0x108(%rsp), %rax
cmpq %rax, %r13
setne %al
movq 0x18(%rsp), %rcx
andb %al, %cl
movb $0x1, %r14b
cmpb $0x1, %cl
jne 0x7963
movslq 0x20(%r13), %rax
leaq (%rax,%rax,2), %rdi
shlq $0x4, %rdi
addq 0x28(%rsp), %rdi
leaq 0x100(%rsp), %rsi
callq 0xe73a
movq %r13, %rdi
callq 0x2250
movq %rax, %r13
leaq 0x108(%rsp), %rax
cmpq %rax, %r13
jne 0x7923
movb $0x1, %r14b
jmp 0x7963
movl 0x18(%rsp), %r14d
leaq 0x100(%rsp), %rdi
callq 0xe2fa
leaq 0x98(%rsp), %rdi
callq 0xe9c2
testb $0x1, %r14b
jne 0x7999
movq 0x40(%rsp), %rax
incq %rax
cmpq 0x138(%rsp), %rax
jne 0x7663
leaq 0x140(%rsp), %rdi
callq 0xe2fa
leaq 0x170(%rsp), %r13
movq %r13, %rdi
callq 0xe2fa
testb $0x1, %r14b
movq 0x130(%rsp), %rdi
jne 0x79dd
callq 0x2160
movq %rax, %rcx
leaq 0xd8(%rsp), %rax
cmpq %rax, %rcx
jne 0x760e
leaq 0xd0(%rsp), %rdi
callq 0x1154a
movq 0x28(%rsp), %r13
movq 0x30(%rsp), %r14
cmpq %r14, %r13
je 0x7a28
movq %rbx, %rdi
movq %r13, %rsi
callq 0xe39a
leaq 0xd0(%rsp), %rdi
movq %rbx, %rsi
callq 0xd80a
movl $0x1, (%rax)
movq %rbx, %rdi
callq 0xe2fa
addq $0x30, %r13
jmp 0x79f4
movq 0xc8(%rsp), %rcx
movslq %ecx, %rcx
movq 0xf8(%rsp), %rax
cmpq %rcx, %rax
cmovnel %eax, %ecx
movq %rcx, 0xc8(%rsp)
leaq 0x170(%rsp), %r13
jne 0x75f2
xorps %xmm0, %xmm0
movq 0x20(%rsp), %r14
movups %xmm0, 0x60(%r14)
movups %xmm0, 0x50(%r14)
movups %xmm0, 0x40(%r14)
movups %xmm0, 0x30(%r14)
movups %xmm0, 0x20(%r14)
movups %xmm0, 0x10(%r14)
leaq 0x178(%rsp), %rax
movl $0x0, (%rax)
xorl %r13d, %r13d
movq %r13, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
movq %r13, 0x20(%rax)
movq 0xe8(%rsp), %rbx
leaq 0xd8(%rsp), %rax
cmpq %rax, %rbx
je 0x7b0a
xorl %r13d, %r13d
leaq 0x50(%rsp), %r15
leaq 0x170(%rsp), %r12
leaq 0x20(%rbx), %rsi
movq %r15, %rdi
callq 0xe39a
movl 0x50(%rbx), %eax
movl %eax, 0x80(%rsp)
movq %r12, %rdi
movq %r15, %rsi
callq 0xd80a
movl %r13d, (%rax)
incl %r13d
movq %r15, %rdi
callq 0xe2fa
movq %rbx, %rdi
callq 0x2160
movq %rax, %rbx
leaq 0xd8(%rsp), %rax
cmpq %rax, %rbx
jne 0x7ac3
movq %r13, 0x18(%rsp)
movl %r13d, %esi
leaq 0x140(%rsp), %rdi
leaq 0x50(%rsp), %rdx
callq 0xdc7a
movq 0x10(%rsp), %r14
cmpl $0x0, 0x4(%r14)
jle 0x7be4
xorl %ecx, %ecx
leaq 0x170(%rsp), %rbx
leaq 0x50(%rsp), %r15
movq 0x58(%r14), %rax
movq %rcx, 0x40(%rsp)
leaq (%rcx,%rcx,2), %rbp
shlq $0x4, %rbp
leaq (%rax,%rbp), %r13
addq $0x8, %r13
movq 0x10(%r13), %r12
cmpq %r13, %r12
je 0x7bca
movq 0x20(%r12), %rax
movq %rax, 0x50(%rsp)
movslq 0x54(%rsp), %rax
leaq (%rax,%rax,2), %rsi
shlq $0x4, %rsi
addq 0x28(%rsp), %rsi
movq %rbx, %rdi
callq 0xd80a
movl (%rax), %r14d
movq 0x28(%rsp), %rsi
addq %rbp, %rsi
movq %rbx, %rdi
callq 0xd80a
movslq (%rax), %rax
leaq (%rax,%rax,2), %rdi
shlq $0x4, %rdi
addq 0x140(%rsp), %rdi
movq %r15, %rsi
callq 0xd87a
movl %r14d, (%rax)
movq %r12, %rdi
callq 0x2160
movq %rax, %r12
cmpq %r13, %rax
jne 0x7b65
movq 0x40(%rsp), %rcx
incq %rcx
movq 0x10(%rsp), %r14
movslq 0x4(%r14), %rax
cmpq %rax, %rcx
jl 0x7b43
movq 0x20(%rsp), %rbp
leaq 0x58(%rbp), %rdi
leaq 0x140(%rsp), %rsi
callq 0xd994
movl (%r14), %eax
movl %eax, (%rbp)
movq 0x18(%rsp), %rax
movl %eax, 0x4(%rbp)
xorl %eax, %eax
movl %eax, 0x8(%rbp)
movq %r14, %rcx
leaq 0x58(%rsp), %r14
movl %eax, (%r14)
movq %rax, 0x8(%r14)
movq %r14, 0x10(%r14)
movq %r14, 0x18(%r14)
movq %rax, 0x20(%r14)
movq 0x40(%rcx), %r12
movq 0x48(%rcx), %r13
cmpq %r13, %r12
je 0x7c6f
leaq 0x170(%rsp), %rbx
leaq 0x50(%rsp), %r15
movslq (%r12), %rax
leaq (%rax,%rax,2), %rsi
shlq $0x4, %rsi
addq 0x28(%rsp), %rsi
movq %rbx, %rdi
callq 0xd80a
movq %r15, %rdi
movq %rax, %rsi
callq 0xffc0
addq $0x4, %r12
cmpq %r13, %r12
jne 0x7c42
movq 0x68(%rsp), %rbx
cmpq %r14, %rbx
movq 0x18(%rsp), %r13
je 0x7cc5
leaq 0x40(%rbp), %r15
leaq 0x98(%rsp), %r12
movl 0x20(%rbx), %eax
movl %eax, 0x98(%rsp)
movq 0x48(%rbp), %rsi
cmpq 0x50(%rbp), %rsi
je 0x7caa
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x48(%rbp)
jmp 0x7cb5
movq %r15, %rdi
movq %r12, %rdx
callq 0xef7e
movq %rbx, %rdi
callq 0x2250
movq %rax, %rbx
cmpq %r14, %rax
jne 0x7c8a
movq 0x48(%rbp), %rax
subq 0x40(%rbp), %rax
leaq 0x10(%rbp), %rdi
shrq $0x2, %rax
movl %eax, 0xc(%rbp)
movq 0x10(%rsp), %rsi
addq $0x10, %rsi
callq 0xd8de
movl $0x0, 0x98(%rsp)
testl %r13d, %r13d
jle 0x7d3a
leaq 0x28(%rbp), %rbx
xorl %eax, %eax
leaq 0x98(%rsp), %r14
movq 0x30(%rbp), %rsi
cmpq 0x38(%rbp), %rsi
je 0x7d1a
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x30(%rbp)
jmp 0x7d25
movq %rbx, %rdi
movq %r14, %rdx
callq 0xef7e
movl 0x98(%rsp), %eax
incl %eax
movl %eax, 0x98(%rsp)
cmpl %r13d, %eax
jl 0x7d04
leaq 0x50(%rsp), %rdi
callq 0xe2fa
leaq 0x140(%rsp), %rdi
callq 0x44a0
leaq 0x170(%rsp), %rdi
callq 0xe66c
leaq 0xd0(%rsp), %rdi
callq 0xe66c
leaq 0x28(%rsp), %rdi
callq 0xdaf2
leaq 0x1d8(%rsp), %rdi
callq 0xe2fa
leaq 0x208(%rsp), %rdi
callq 0xe2fa
movq %rbp, %rax
addq $0x238, %rsp            # imm = 0x238
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x7dc7
jmp 0x7e0b
movq %rax, %rbx
jmp 0x7e1b
jmp 0x7de4
jmp 0x7dc7
jmp 0x7dc7
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0xe2fa
jmp 0x7e20
movq %rax, %rbx
jmp 0x7e20
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0xe2fa
jmp 0x7e0e
jmp 0x7dfe
jmp 0x7df6
jmp 0x7ddc
movq %rax, %rbx
jmp 0x7ebc
movq %rax, %rbx
jmp 0x7ec6
movq %rax, %rbx
jmp 0x7ea2
jmp 0x7df6
movq %rax, %rbx
jmp 0x7eaf
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
jmp 0x7eaa
movq %rax, %rbx
leaq 0x140(%rsp), %rdi
callq 0x44a0
movq 0x20(%rsp), %r14
leaq 0x170(%rsp), %rdi
callq 0xe66c
movq %r14, %rdi
callq 0x3bea
jmp 0x7eaf
jmp 0x7e3d
jmp 0x7e3d
jmp 0x7e3d
movq %rax, %rbx
jmp 0x7e7b
jmp 0x7e44
movq %rax, %rbx
leaq 0x1a8(%rsp), %rdi
callq 0xe2fa
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x7e71
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x2200
leaq 0x50(%rsp), %rdi
callq 0xe2fa
leaq 0x100(%rsp), %rdi
callq 0xe2fa
leaq 0x98(%rsp), %rdi
callq 0xe9c2
leaq 0x140(%rsp), %rdi
callq 0xe2fa
leaq 0x170(%rsp), %rdi
callq 0xe2fa
leaq 0xd0(%rsp), %rdi
callq 0xe66c
leaq 0x28(%rsp), %rdi
callq 0xdaf2
leaq 0x1d8(%rsp), %rdi
callq 0xe2fa
leaq 0x208(%rsp), %rdi
callq 0xe2fa
movq %rbx, %rdi
callq 0x2350