graph LR 0--A-->66 0--C-->68 0--Z-->91 66--C-->69 66--D-->70
69的字节点为74和75, 权重为74-5=69和75-5=70, 分别是E和F
1 2 3 4 5 6 7 8
graph LR 0--A-->66 0--C-->68 0--Z-->91 66--C-->69 66--D-->70 69--E-->74 69--F-->75
当然,后面的笔者就不进行模拟了,到此为止。
4. 双数组字典树的构建算法
首先算法的第一步是构建一颗字典树,你需要将这颗字典树构建出来。字典树的代码如下,这个不用多说了
1 2 3 4 5 6 7 8 9
voidaddTire(constchar* str, int len) { int root = 1; for (int i = 0; i < len; i++) { if (tire[root][str[i]] == 0) { tire[root][str[i]] = ++tireTot; } root = tire[root][str[i]]; } }
第二步,就是在字典树上进行BFS,在BFS过程中增量构建双数组字典树,当我们BFS到某个节点U的时候,便开始寻找,当前还有哪个base值没有被使用,可以使得这个U的子节点的check值均为0, no BB , show code
先找到U的所有子节点
1 2 3 4 5 6 7 8
vector<int> sonTransList; for (int i = 0;i < maxCharest;i++) { if (tire[tireTop][i] != 0) { sonTransList.push_back(i); tireQ.push(tire[tireTop][i]); } } cout << "find son: " << sonTransList.size() << endl;;
然后寻找一个合适的base值,这个值储存在变量begin中
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// find begin while (true) { begin++; bool ok = true; for (int son : sonTransList) { if (check[begin + code[son]] != 0) { ok = false; break; } } if (ok) { break; } }
while (!tireQ.empty()) { int tireTop = tireQ.front(); tireQ.pop();
vector<int> sonTransList; for (int i = 0;i < maxCharest;i++) { if (tire[tireTop][i] != 0) { sonTransList.push_back(i); tireQ.push(tire[tireTop][i]); } } cout << "find son: " << sonTransList.size() << endl;;
// find begin while (true) { begin++; bool ok = true; for (int son : sonTransList) { if (check[begin + code[son]] != 0) { ok = false; break; } } if (ok) { break; } }
base[tireState2DatState[tireTop]] = begin; for (int i = 0;i < maxCharest;i++) { if (tire[tireTop][i] != 0) { int son = i; if (check[begin + code[son]] != 0) { exit(-1); } check[begin + code[son]] = begin; tireState2DatState[tire[tireTop][i]] = begin + code[son]; } } for (int i = 0;i < 1000;i++) { if (check[i] != 0 || base[i] != 0) { cout << i << " " << base[i] << " " << check[i] << endl; } } cout <<begin<<"--------" << endl; }
}
intmain() {
for (int i = 0;i < 7;i++) { addTire(stringData[i].data(), stringData[i].size()); } buildDAT();