编译原理:偶数个0偶数个1 的正规式为什么是(00|11 | ( (01|10) (00|11) * (01| 10)))*

首先应该明确一下问题

我们的问题等价于“偶数个0偶数个1的正规式是什么”,而不是“(00|11 | ( (01|10) (00|11) * (01| 10))) *就能表示偶数个0偶数个1 的正规式”。

可以想一下,在二进制串中0和1的个数的状态无非以下四种:

  1. 偶数个0,偶数个1 -------------0
  2. 偶数个0,奇数个1 -------------①
  3. 奇数个0,偶数个1 -------------②
  4. 奇数个0,奇数个1 -------------③

注:虚线后面的数值是相应的状态,我们将在接下来的状态转换图中看到

  • 接下来我们画一下状态转换图:

在这里插入图片描述
注:圆内的是状态值,箭头旁边的是二进制值
箭头的方向和箭头旁的数值需要结合状态值的意义理解

  • 接下来,我们把1状态拿掉,整理之后是这样的:
    在这里插入图片描述

  • 接下来,把2状态拿掉,整理之后是这样的:
    在这里插入图片描述

  • 接下来,把状态3拿掉,整理之后是这样的:
    在这里插入图片描述

  • 进而可以表示为:(00|11 | (01|10) (00|11) * (01| 10))*
    注:该式与题目中的少一个括号,其实是一样的,因为连接运算的优先级大于选择运算 |

  • 现在我们尝试用代码实现图一:

#include<iostream>
int main()
{
    using namespace std;
    int mov(int,int);
    string s="";
    cout<<"请输入一个二进制序列"<<endl;
    cin>>s;
    int i=0;
    int b=-1;
    int im=0;
    int om=-1;
    for(i=0;i<s.size();++i)
    {
        b=s[i]-'0';//将字符转换为数字
        om=mov(im,b);
        im=om;
    }
    switch(om)
    {
    case 0:
        cout<<"成功,您输入了偶数个0偶数个1!!"<<endl;
        break;
    case 1:
        cout<<"您输入了偶数个0奇数个1,下次可以多输入一个1"<<endl;
        break;
    case 2:
        cout<<"您输入了奇数个0偶数个1,下次可以多输入一个0"<<endl;
        break;
    case 3:
        cout<<"您输入了奇数个0奇数个1,下次可以01各多输入一个"<<endl;
        break;
    default:
        ;
    }
    return 0;
}
int mov(int im, int b)//b是0或1
{
    int om=0;//保存move函数的输出,将作为返回值
    switch(im)
    {
    case 0:
        if(b==0)
            om=2;
        else
            om=1;
        break;
    case 1:
        if(b==0)
            om=3;
        else
            om=0;
        break;
    case 2:
        if(b==0)
            om=0;
        else
            om=3;
        break;
    case 3:
        if(b==0)
            om=1;
        else
            om=2;
        break;
    default:
        ;
    }
    return om;
}

运行一下,就可以判断输入的二进制串是否包含偶数个0和偶数个1啦

  • 57
    点赞
  • 125
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值