题意

一个DFA可以用一个5元组  $((Q, \sum , \delta , q_0, F))$ 表示,其中 $Q$ 为状态集,$\sum$ 为字母表,$\delta$ 为转移函数,$q_0$ 为起始状态,$F$ 为终态集。给出两个 DFA(有限状态自动机),判断他们是否等价。

分析

一个简单的做法:把 “a和b” 等价转化为 "a" 的补和 "b" 不相交,且 "b" 的补和 'a" 不相交。

如何求 DFA 的补?也就是把接受的串变成不接受的串,不接受的串变成接受的串。由此可想到,只需把终态和非终态互换即可。

如何判断两个 DFA 不相交?可试着找一个可同时被两个 DFA 接受的串,如果找不到,则说明两个 DFA 不相交。如何找到这个串?构造一个新的 DFA,它的每个状态都可以写成($q_1, q_2$),其中 $q_1$ 和 $q_2$ 分别是两个 DFA 中的状态,当且仅当 $q_1$ 和 $q_2$ 分别是两个 DFA 的终态时,($q_1, q_2$)是新DFA的终态。这样,问题转化为:找一个能被新DFA接受的串。只需要用经典的图的遍历(DFS 或 BFS)即可。

还有一个问题,对于“该转移不存在” 的处理。虽然可以直接处理,但更经典的做法是加一个“所有转移都指向自己“的”孤岛状态”,把所有不存在的转移都改成转移到孤岛。在下面的代码实现中,是将每个状态编号加1,留出状态0作为孤岛状态。

#include<bits/stdc++.h>
using namespace std; const int maxn = + ;
const int max_siz = + ;
int siz, sta1, sta2, a1[maxn][max_siz], a2[maxn][max_siz];
bool vis[maxn][maxn]; bool judge(int x1, int x2) //终态判定
{
return a1[x1][] ^ a2[x2][];
} bool dfs(int x1, int x2) //存在公共串返回true
{
vis[x1][x2] = true;
if(judge(x1, x2)) return true; for(int i = ;i <= siz;i++)
{
int next1 = a1[x1][i], next2 = a2[x2][i];
if(!vis[next1][next2])
{
if(dfs(next1, next2))
return true;
}
}
return false;
} int main()
{
int kase = ;
while(scanf("%d", &siz) == && siz)
{
scanf("%d", &sta1);
for(int i = ;i <= sta1;i++)
for(int j = ;j <= siz;j++)
{
int tmp;
scanf("%d", &tmp);
a1[i][j] = tmp+(j!=);
} scanf("%d", &sta2);
for(int i = ;i <= sta2;i++)
for(int j = ;j <= siz;j++)
{
int tmp;
scanf("%d", &tmp);
a2[i][j] = tmp+(j!=);
} memset(vis, , sizeof(vis));
printf("Case #%d: ", ++kase);
if(dfs(, )) printf("No\n");
else printf("Yes\n");
}
}

参考链接:

1. https://www.luogu.org/problemnew/solution/UVA1671

2.https://blog.csdn.net/programmerya/article/details/81350287

UVa 1671 语言的历史——判断两个DFA是否等价的更多相关文章

  1. C语言位操作--判断两整数是否异号

    判断两整数是否异号: int x, y; //输入比较的两数 bool f = ((x ^ y) < 0); // 返回真,当且仅当x与y异号 说明:当x.y异号,x与y的最高位分别为0和1,取 ...

  2. [uva] 1671 History of Languages

    题目描述 输入两个DFA,判断是否等价. https://uva.onlinejudge.org/external/16/1671.pdf 输入 第一行T 可以接受的字母表 第二行N 状态数 接下去N ...

  3. [置顶] 如何判断两个IP大小关系及是否在同一个网段中

    功能点  判断某个IP地址是否合法 判断两个IP地址是否在同一个网段中 判断两个IP地址的大小关系 知识准备 IP协议 子网掩码 Java 正则表达式 基本原理 IP地址范围 0.0.0.0- 255 ...

  4. Java与JavaScript中判断两字符串是否相等的区别

    JavaScript是一种常用的脚本语言,这也决定了其相对于其他编程语言显得并不是很规范.在JavaScript中判断两字符串是否相等 直接用==,这与C++里的String类一样.而Java里的等号 ...

  5. Java 判断两个对象是否相等

    一.使用 == 与 equals == : 它的作用是判断两个对象的地址是不是相等.即,判断两个对象是不是同一个对象.(基本数据类型==比较的是值,引用数据类型==比较的是内存地址) equals() ...

  6. Java基础(六)判断两个对象相等:equals、hashcode、toString方法

    1.equal方法 Object类中的equal方法用于检测一个对象是否等于另外一个对象.在Object类中,这个方法将判断两个对象是否具有相同的引用.如果两个对象具有相同的引用,它们一定是相等的.然 ...

  7. C# 判断两条直线距离

    本文告诉大家获得两条一般式直线距离 一般式的意思就是 Ax+By+C=0" role="presentation">Ax+By+C=0Ax+By+C=0 如果有两个 ...

  8. 2018-7-31-C#-判断两条直线距离

    title author date CreateTime categories C# 判断两条直线距离 lindexi 2018-07-31 14:38:13 +0800 2018-05-08 10: ...

  9. 【跟着子迟品 underscore】JavaScript 中如何判断两个元素是否 "相同"

    Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...

随机推荐

  1. IDEA 自定义代码模板

    IDEA 自定义代码模板操作步骤:

  2. 面试官问你MySQL的优化,看这篇文章就够了

    作者:zhangqh segmentfault.com/a/1190000012155267 一.EXPLAIN 做MySQL优化,我们要善用 EXPLAIN 查看SQL执行计划. 下面来个简单的示例 ...

  3. stm32F103片上串口USART1通信实验

    硬件说明:如原理图所示, 103的PA10 PA11分别接CP2102usb转串口芯片的TXD RXD引脚.CP2102芯片是将串口和电脑USB接口进行了转接,方便应用灵活. 片上串口驱动代码如下. ...

  4. Wing电信平台操作方法

    Wing电信平台操作文档 当前文档编制于2019/9/3 一.登陆 登陆网址 https://www.ctwing.cn/ 点击右上角控制台 点击左侧栏点击产品中心 选择需要注册的产品 二.注册设备 ...

  5. wait(),notify(),notifyAll()必须加锁的原因

    从语义方面解析为什么需要锁: 1.wait()方法会释放锁,如果没有先获得锁,那么如何释放? 从实际的作用: 为了预防饥饿线程的产生. 原因: // 线程A 的代码 while(!condition) ...

  6. [洛谷P3966][TJOI2013]单词

    题目大意:有$n$个字符串,求每个字符串在所有字符串中出现的次数 题解:$AC$自动机,每个节点被经过时$sz$加一,每一个字符串出现次数为其$fail$树子树$sz$和 卡点:$AC$自动机根节点为 ...

  7. [洛谷P3227][HNOI2013]切糕

    题目大意:有一个$n\times m$的切糕,每一个位置的高度可以在$[1,k]$之间,每个高度有一个代价,要求四联通的两个格子之间高度最多相差$D$,问可行的最小代价.$n,m,k,D\leqsla ...

  8. 使用DOS命令登录管理员并添加账号管理员权限

    runas /user:administrator cmd Password: compmgmt.msc

  9. Java冒泡排序与快速排序笔记

    public class Sort { public static void sort() { Scanner input = new Scanner(System.in); int sort[] = ...

  10. Java File类与IO流

    File 类 java.io.File 文件和目录路径名的抽象表示形式, 对文件或目录进行操作 构造方法: File(File parent, String child) : 根据 parent 抽象 ...