HDU 2471 History of Languages

题目大意:

给出两个状态数不超过2000的DFA, 判断是否同构. 同构的意思是能识别的语言完全相同. 字符集最大26.

 

简要分析:

本来想把所有字符串从一个DFA里面搞出来, 再对另一个DFA进行黑箱测试, 但一看样例, 有环!!! 也就是说, 它们能识别的语言可以是无限的!

于是就只好曓搜了, 用(i, j)二元组表示两台自动机分别在状态i和j, 从(0, 0)开始广搜, 搜出一个二元组(i, j), 则两台DFA同构的充分条件是状态i和状态j相同, 这里判断相同考虑两方面就行了: 是否同为final态(或者叫accept态?)或同不为, 转移方式是否完全相同. 若所有的二元组能满足, 则可以判断两台DFA同构了. 设DFA状态数为N, 字符集大小为T, 则时间复杂度为O(TN^2).

 

代码实现:

View Code
 1 #include <cstdio>
2 #include <cstdlib>
3 #include <cstring>
4 #include <utility>
5 #include <queue>
6 #include <algorithm>
7 using namespace std;
8
9 typedef pair <int, int> pt;
10 const int MAX_T = 26, MAX_N = 2000, SEED = 99991;
11 int n[2], t;
12 bool vis[MAX_N][MAX_N], can_use[MAX_N], cal[MAX_N];
13 queue <pt> q;
14
15 struct node_t {
16 int son[MAX_T], end;
17 int mask;
18 int calc_mask() {
19 mask = 0;
20 for (int i = 0; i < t; i ++)
21 if (son[i] >= 0) mask |= 1 << i;
22 mask = mask << 1 | end;
23 return mask;
24 }
25 } dfa[2][MAX_N];
26
27 bool dfs(int k, int u) {
28 if (cal[u]) return can_use[u];
29 cal[u] = 1;
30 if (dfa[k][u].end) can_use[u] = 1;
31 for (int i = 0; i < t; i ++)
32 if (dfa[k][u].son[i] >= 0 && dfs(k, dfa[k][u].son[i])) can_use[u] = 1;
33 return can_use[u];
34 }
35
36 void dfs_again(int k, int u) {
37 if (cal[u]) return;
38 cal[u] = 1;
39 for (int i = 0; i < t; i ++)
40 if (dfa[k][u].son[i] >= 0) {
41 if (can_use[dfa[k][u].son[i]]) dfs(k, dfa[k][u].son[i]);
42 else dfa[k][u].son[i] = -1;
43 }
44 }
45
46 void init(int k) {
47 memset(can_use, 0, sizeof(can_use));
48 memset(cal, 0, sizeof(cal));
49 dfs(k, 0);
50 memset(cal, 0, sizeof(cal));
51 dfs_again(k, 0);
52 }
53
54 bool solve() {
55 memset(vis, 0, sizeof(vis));
56 while (q.size()) q.pop();
57 q.push(make_pair(0, 0));
58 vis[0][0] = 1;
59 while (q.size()) {
60 pt u = q.front();
61 q.pop();
62 if (dfa[0][u.first].mask != dfa[1][u.second].mask) return 0;
63 for (int i = 0; i < t; i ++)
64 if (dfa[0][u.first].son[i] >= 0) {
65 pt v = make_pair(dfa[0][u.first].son[i], dfa[1][u.second].son[i]);
66 if (!vis[v.first][v.second]) {
67 vis[v.first][v.second] = 1;
68 q.push(v);
69 }
70 }
71 }
72 return 1;
73 }
74
75 int main() {
76 int cas = 0;
77 while (scanf("%d", &t) != EOF && t) {
78 for (int k = 0; k < 2; k ++) {
79 scanf("%d", &n[k]);
80 for (int i = 0; i < n[k]; i ++) {
81 scanf("%d", &dfa[k][i].end);
82 for (int j = 0; j < t; j ++) scanf("%d", &dfa[k][i].son[j]);
83 }
84 init(k);
85 for (int i = 0; i < n[k]; i ++) dfa[k][i].calc_mask();
86 }
87
88 printf("Case #%d: ", ++ cas);
89 if (solve()) printf("Yes\n");
90 else printf("No\n");
91 }
92 return 0;
93 }

你可能感兴趣的:(language)