• 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 = 2000 + 10;
    const int max_siz = 26 + 5;
    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][0] ^ a2[x2][0];
    }
    
    bool dfs(int x1, int x2)   //存在公共串返回true
    {
        vis[x1][x2] = true;
        if(judge(x1, x2))  return true;
    
        for(int i = 1;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 = 0;
        while(scanf("%d", &siz) == 1 && siz)
        {
            scanf("%d", &sta1);
            for(int i = 1;i <= sta1;i++)
                for(int j = 0;j <= siz;j++)
                {
                    int tmp;
                    scanf("%d", &tmp);
                    a1[i][j] = tmp+(j!=0);
                }
    
            scanf("%d", &sta2);
            for(int i = 1;i <= sta2;i++)
                for(int j = 0;j <= siz;j++)
                {
                    int tmp;
                    scanf("%d", &tmp);
                    a2[i][j] = tmp+(j!=0);
                }
    
    
            memset(vis, 0, sizeof(vis));
            printf("Case #%d: ", ++kase);
            if(dfs(1, 1))  printf("No
    ");
            else  printf("Yes
    ");
        }
    }

    参考链接:

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

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

  • 相关阅读:
    5-把自己的系统刷到开发板
    4-构建网络文件系统
    ipc
    advio
    pthread
    signal
    process_control
    python3.6+selenium_Testsuits测试套件
    python3.6+selenium_多个测试用例
    jQuery的九类选择器
  • 原文地址:https://www.cnblogs.com/lfri/p/11425266.html
Copyright © 2020-2023  润新知