UVa 1671 语言的历史——判断两个DFA是否等价
题意
一个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是否等价的更多相关文章
- C语言位操作--判断两整数是否异号
判断两整数是否异号: int x, y; //输入比较的两数 bool f = ((x ^ y) < 0); // 返回真,当且仅当x与y异号 说明:当x.y异号,x与y的最高位分别为0和1,取 ...
- [uva] 1671 History of Languages
题目描述 输入两个DFA,判断是否等价. https://uva.onlinejudge.org/external/16/1671.pdf 输入 第一行T 可以接受的字母表 第二行N 状态数 接下去N ...
- [置顶] 如何判断两个IP大小关系及是否在同一个网段中
功能点 判断某个IP地址是否合法 判断两个IP地址是否在同一个网段中 判断两个IP地址的大小关系 知识准备 IP协议 子网掩码 Java 正则表达式 基本原理 IP地址范围 0.0.0.0- 255 ...
- Java与JavaScript中判断两字符串是否相等的区别
JavaScript是一种常用的脚本语言,这也决定了其相对于其他编程语言显得并不是很规范.在JavaScript中判断两字符串是否相等 直接用==,这与C++里的String类一样.而Java里的等号 ...
- Java 判断两个对象是否相等
一.使用 == 与 equals == : 它的作用是判断两个对象的地址是不是相等.即,判断两个对象是不是同一个对象.(基本数据类型==比较的是值,引用数据类型==比较的是内存地址) equals() ...
- Java基础(六)判断两个对象相等:equals、hashcode、toString方法
1.equal方法 Object类中的equal方法用于检测一个对象是否等于另外一个对象.在Object类中,这个方法将判断两个对象是否具有相同的引用.如果两个对象具有相同的引用,它们一定是相等的.然 ...
- C# 判断两条直线距离
本文告诉大家获得两条一般式直线距离 一般式的意思就是 Ax+By+C=0" role="presentation">Ax+By+C=0Ax+By+C=0 如果有两个 ...
- 2018-7-31-C#-判断两条直线距离
title author date CreateTime categories C# 判断两条直线距离 lindexi 2018-07-31 14:38:13 +0800 2018-05-08 10: ...
- 【跟着子迟品 underscore】JavaScript 中如何判断两个元素是否 "相同"
Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...
随机推荐
- postman上传文件对参数的contentType类型设置方式
项目中使用postman模拟上传文件接口时,总是不成功,发现content-type设置不对,设置head的contentType后,还是不行,后来无意中发现文件参数默认的content-type类型 ...
- Apache Kafka Connect - 2019完整指南
今天,我们将讨论Apache Kafka Connect.此Kafka Connect文章包含有关Kafka Connector类型的信息,Kafka Connect的功能和限制.此外,我们将了解Ka ...
- FireDAC 中文字段过滤问题
当使用 FireDAC Filter 过滤数据的时候,通常这样写: FDMemTable.Filtered := False; FDMemTable1.Filter := '姓名=' + strin ...
- web页面元素定位
所有web网页中有8种元素定位方式 靠单一的特征找元素:6种(id,class_name,tag_name,name,link_text(2))组合各种特征和关系来找元素:2种(xpath,css) ...
- xorm -Alias,Asc,Desc方法实例
Alias(string)给Table设定一个别名 package main import ( "fmt" _ "github.com/go-sql-driver/mys ...
- 阿里企业邮箱smtp设置
阿里的邮箱没有SMTP授权码信息 SMTP服务器:smtp.mxhichina.com
- 【转载】Javascript使用Math.random()随机数函数生成1至1000的随机数
在Javascript代码编写过程中,有时候我们需要使用Js来生成随机数,清除ajax的get请求缓存的时候我们会带上一个随机数来解决此问题,此外在其他应用中也可能使用到随机数,在Javascript ...
- Node.js学习之(第二章:exports和module.exports)
前言 Node中,每个模块都有一个exports接口对象,我们需要把公共的方法或者字符串挂载在这个接口对象中,其他的模块才可以使用. Node.js中只有模块作用域,默认两个模块之间的变量,方法互不冲 ...
- ABAP开发环境终于支持以驼峰命名法自动格式化ABAP变量名了
Jerry进入SAP成都研究院前,一直是用C/C++开发,所以刚接触ABAP,对于她在某些语法环境下大小写敏感,某些环境下不敏感的特性很不适应.那时候Jerry深深地怀念之前在C/C++编程时遵循的驼 ...
- HDFS读流程
客户端先与NameNode通信,获取block位置信息,之后线性地先取第一个块,然后接二连三地获取,取回一个块时会进行MD5验证,验证通过后会使read顺利进行完,当最终读完所有的block块之后,拼 ...