剑指 Offer 20. 表示数值的字符串(确定的有穷自动机DFA)

题目

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、“±5”、"-1E-16"及"12e+5.4"都不是。

解题思路

下面是DFA:
状态转换图.jpg

注:

  • 用一个vector内层使用map来保存状态之间的转移。
  • 去掉首位空格后建立的自动机,加上空格也可以,只是状态会多出来一个(尾部多出一个识别空格的状态)。
  • 小数点前面可以没有数字,对应状态8。
  • 小数点后面也可以没有数字,对应状态3为接收状态和3后面直接跟e指数等。
  • 接受状态:2、3、4、7。

代码

class Solution {
public:
    bool isNumber(string s) {
        if(s.size() == 0){
            return false;
        }
        //运用状态机进行判断
        //1.先去掉首尾空格
        int n = s.size();
        int start = 0;
        int end = n - 1;
        //全部是空格的字符串
        while(start < n && s[start] == ' '){
            ++start;
        }
        if(start == n){
            return false;
        }
        while(end >= 0 && s[end] == ' '){
            --end;
        }
        //然后用状态机进行判断,一共8个状态:
        int state = 0;
        //状态机判断
        judge(s, start, end, state);

        if(state == 2 || state == 3 || state == 4 || state == 7){
            return true;
        }
        return false;
    }
private:
    //状态机的9个状态,2、3、4、7是接收状态
    //0.初始状态
    //1.含有底数前符号+/-
    //2.小数点前数字
    //3.小数点
    //4.小数点后数字
    //5.e指数
    //6.e后面指数的符号
    //7.指数的数字  
    //8.小数点前没有数字
    vector<unordered_map<char, int>> myMap;

    void judge(string s, int start, int end, int &state){
        myMap = vector<unordered_map<char, int>>(9);
        myMap[0] = {{'+', 1}, {'-', 1}, {'d', 2}, {'.', 8}};    //注:小数点前没有数字也符合
        myMap[1] = {{'d', 2}, {'.', 8}};
        myMap[2] = {{'d', 2}, {'.', 3}, {'e', 5}};
        myMap[3] = {{'d', 4}, {'e', 5}};
        myMap[4] = {{'d', 4}, {'e', 5}};
        myMap[5] = {{'+', 6}, {'-', 6}, {'d', 7}};
        myMap[6] = {{'d', 7}};
        myMap[7] = {{'d', 7}};
        myMap[8] = {{'d', 4}};

        for(int i = start; i <= end; ++i){
            char c = s[i];
            if(c >= '0' && c <= '9'){   //数字
                c = 'd';
                if(myMap[state].count(c)){
                    state = myMap[state][c];
                }
                else{   //非法输入,不能进行状态转换,直接将state置为0
                    state = 0;  //0不是接收状态,置为0,然后返回
                    return;
                }
            }
            else{
                if(myMap[state].count(c)){
                    state = myMap[state][c];
                }
                else{   //非法输入,不能进行状态转换,直接将state置为0
                    state = 0;  //0不是接收状态,置为0,然后返回
                    return;
                }
            }
        }
    }
};
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值