原理P51页
重点
move操作
不包含本身元素
只传递一次
空闭包closure操作
包含本身元素
无限传递
运行效果
项目源码
#include <bits/stdc++.h>
using namespace std;
int m;
int start = -1;
// 结构体
struct edge {
int v;
char c;
};
vector<edge> e[1005], transferFunction[1005]; // 建图
bool vis[1005]; // 节点是否被访问过
// 单元素*闭包(空-闭包)
void null_closure_one(int u, vector<int> & a) {
a.push_back(u);
for (auto p : e[u]) {
int v = p.v;
char c = p.c;
if (c == '*' && !vis[v]) {
vis[v] = true;
null_closure_one(v, a);
}
}
}
// 数组*闭包(空-闭包)
vector<int> null_closure_mul(vector<int> A) {
memset(vis, false, sizeof(vis));
vector<int> ans;
for (auto x : A) {
null_closure_one(x, ans);
}
sort(ans.begin(), ans.end());
return ans;
}
// 单元素move
void move_one(int u, char c, vector<int> & a) {
for (auto p : e[u]) {
int v = p.v;
char cc = p.c;
if (cc == c && !vis[v]) {
vis[v] = true;
a.push_back(v);
}
}
}
// 数组move
vector<int> move_mul(vector<int> A, char c) {
memset(vis, false, sizeof(vis));
vector<int> ans;
for (auto x : A) {
move_one(x, c, ans);
}
sort(ans.begin(), ans.end());
return ans;
}
map<vector<int>, int> done; // 子集是否被访问过
vector<vector<int>> C; // 子集组
vector<int> T; // 对应课本中的 T0 T1 T2 ...
int cnt = 0; //用来存储T对应的下标, 最后有cnt个子集被标记
set<char> sign; // 记录弧的种类
void print_tips() {
cout << "* is null " << endl;
cout << "how many transfor function ? (copy follow example): " << endl;
cout << "---------------------------" << endl;
cout << "13" << endl;
cout << "0 * 1" << endl;
cout << "0 * 7" << endl;
cout << "1 * 2" << endl;
cout << "1 * 4" << endl;
cout << "2 a 3" << endl;
cout << "3 * 6" << endl;
cout << "4 b 5" << endl;
cout << "5 * 6" << endl;
cout << "6 * 1" << endl;
cout << "6 * 7" << endl;
cout << "7 a 8" << endl;
cout << "8 b 9" << endl;
cout << "9 b 10" << endl;
cout << "---------------------------" << endl;
}
void read() {
cin >> m; // 转换函数数量
for (int i = 1; i <= m; ++i) {
int u, v; char c; // u:起点 v:终点 c:弧值
cin >> u >> c >> v;
e[u].push_back({v, c});
sign.insert(c);
if (start == -1) start = u;
}
sign.erase('*'); // 记录所有的弧值(去掉空)
}
void print_Ts() {
cout << "----------------------------------------------" << endl;
int sz = C.size();
for (int i = 0; i < sz; ++i) {
int size = C[i].size();
cout << "T[" << i << "] = {";
for (int j = 0; j < size; ++j) {
printf("%d", C[i][j]);
if (j < size - 1) cout << " , ";
if (j == size - 1) cout << "}\n";
// printf("%d%s", C[i][j], " }\n"[j == size - 1]);
}
}
cout << "----------------------------------------------" << endl;
}
void print_transferFunctions() {
int sz = C.size();
// 打印
for (int i = 0; i < sz; ++i) {
for (auto p : transferFunction[i]) {
cout << " " << p.c << endl;
cout << "T["<< i <<"]" << " ---> " <<"T[" <<(p.v - 1)<<"]"<< endl;
}
}
cout << endl;
}
void solve() {
memset(vis, false, sizeof(vis));
null_closure_one(start, T);
C.push_back(T);
bool ok = true;
while (ok) { // 试探是否还有没有标记的子集 true代表还有
ok = false;
int sz = C.size();
for (int i = 0; i < sz; ++i) {
vector<int> Tx = C[i];
if (!done[Tx]) { // 该子集未被标记过
ok = true;
done[Tx] = ++cnt; // 标记
for (set<char> :: iterator it = sign.begin(); it != sign.end(); it++) {
memset(vis, false, sizeof(vis));
vector<int> T = null_closure_mul(move_mul(Tx, *it));
if (!done[T]) {
C.push_back(T);
int sz = C.size();
transferFunction[i].push_back({sz, *it}); // 编号为i的子集 通过弧*it 转换到子集 sz
}
else { // 没产生新的子集,也需要记录 转换函数
transferFunction[i].push_back({done[T], *it}); // 编号为i的子集 通过弧*it 转换到子集 done[T]
}
}
}
}
}
}
int main() {
print_tips(); // 打印输入提示
read(); // 对输入进行处理, 存储边
solve(); // 进行move 和 空-闭包操作
print_Ts(); // 打印T集合
print_transferFunctions(); // 打印确定化后的 转换函数
return 0;
}