Leetcode有限状态自动机

在字符串匹配等领域,状态自动机具有很好的统一性、完整性,易于编码,不用去考虑各种边界

LC 8. 字符串转换整数 (atoi)

题解:参考官网题解
本题可以建立如下图所示的自动机:

我们也可以用下面的表格来表示这个自动机:

\[\begin{array}{|l|l|l|l|l|} \hline & \text { ' ' } & \text { +/- } & \text { in_number } & \text { other } \\ \hline \text { start } & \text { start } & \text { signed } & \text { in_number } & \text { end } \\ \hline \text { signed } & \text { end } & \text { end } & \text { in_number } & \text { end } \\ \hline \text { in_number } & \text { end } & \text { end } & \text { in_number } & \text { end } \\ \hline \text { end } & \text { end } & \text { end } & \text { end } & \text { end } \\ \hline \end{array} \]

接下来编程部分就非常简单了:我们只需要把上面这个状态转换表抄进代码即可

class Automaton{
    string state = "start";
    unordered_map<string, vector<string>> table= {
        {"start", {"start", "signed", "in_number", "end"}},
        {"signed", {"end", "end", "in_number", "end"}},
        {"in_number", {"end", "end", "in_number", "end"}},
        {"end", {"end", "end", "end", "end"}}
    };
    int get_col(char ch) {
        if(ch == ' ')  return 0;
        if(ch == '+' || ch == '-')  return 1;
        if(isdigit(ch))  return 2;
        else  return 3;
    }
public:
    int sign = 1;
    long long ans = 0;
    void get(char ch) {
        state = table[state][get_col(ch)];
        if(state == "signed") if(ch=='-')  sign = -1;
        if(state == "in_number") {
            ans = ans*10 + ch-'0';
            if(sign == 1)  ans = min(ans, (long long)INT_MAX);
            if(sign == -1)  ans = min(ans, -(long long)INT_MIN);
        }
    }
};

class Solution {
public:
    int myAtoi(string s) {
        Automaton automaton;
        for(char ch : s)  automaton.get(ch);
        return automaton.sign * automaton.ans;
    }
};

LC 65. 有效数字


注意,这个状态的选择还有挺难的,区分的小数点前和小数点后

class Solution {
public:
    enum State {
        STATE_INITIAL,
        STATE_INT_SIGN,
        STATE_INTEGER,
        STATE_POINT,
        STATE_POINT_WITHOUT_INT,
        STATE_FRACTION,
        STATE_EXP,
        STATE_EXP_SIGN,
        STATE_EXP_NUMBER,
        STATE_END
    };

    enum CharType {
        CHAR_NUMBER,
        CHAR_EXP,
        CHAR_POINT,
        CHAR_SIGN,
        CHAR_ILLEGAL
    };

    CharType toCharType(char ch) {
        if (ch >= '0' && ch <= '9') {
            return CHAR_NUMBER;
        } else if (ch == 'e' || ch == 'E') {
            return CHAR_EXP;
        } else if (ch == '.') {
            return CHAR_POINT;
        } else if (ch == '+' || ch == '-') {
            return CHAR_SIGN;
        } else {
            return CHAR_ILLEGAL;
        }
    }

    bool isNumber(string s) {
        unordered_map<State, unordered_map<CharType, State>> transfer{
            {
                STATE_INITIAL, {
                    {CHAR_NUMBER, STATE_INTEGER},
                    {CHAR_POINT, STATE_POINT_WITHOUT_INT},
                    {CHAR_SIGN, STATE_INT_SIGN}
                }
            }, {
                STATE_INT_SIGN, {
                    {CHAR_NUMBER, STATE_INTEGER},
                    {CHAR_POINT, STATE_POINT_WITHOUT_INT}
                }
            }, {
                STATE_INTEGER, {
                    {CHAR_NUMBER, STATE_INTEGER},
                    {CHAR_EXP, STATE_EXP},
                    {CHAR_POINT, STATE_POINT}
                }
            }, {
                STATE_POINT, {
                    {CHAR_NUMBER, STATE_FRACTION},
                    {CHAR_EXP, STATE_EXP}
                }
            }, {
                STATE_POINT_WITHOUT_INT, {
                    {CHAR_NUMBER, STATE_FRACTION}
                }
            }, {
                STATE_FRACTION,
                {
                    {CHAR_NUMBER, STATE_FRACTION},
                    {CHAR_EXP, STATE_EXP}
                }
            }, {
                STATE_EXP,
                {
                    {CHAR_NUMBER, STATE_EXP_NUMBER},
                    {CHAR_SIGN, STATE_EXP_SIGN}
                }
            }, {
                STATE_EXP_SIGN, {
                    {CHAR_NUMBER, STATE_EXP_NUMBER}
                }
            }, {
                STATE_EXP_NUMBER, {
                    {CHAR_NUMBER, STATE_EXP_NUMBER}
                }
            }
        };

        int len = s.length();
        State st = STATE_INITIAL;

        for (int i = 0; i < len; i++) {
            CharType typ = toCharType(s[i]);
            if (transfer[st].find(typ) == transfer[st].end()) {
                return false;
            } else {
                st = transfer[st][typ];
            }
        }
        return st == STATE_INTEGER || st == STATE_POINT || st == STATE_FRACTION || st == STATE_EXP_NUMBER || st == STATE_END;
    }
};
posted @ 2022-02-24 23:49  Rogn  阅读(304)  评论(0编辑  收藏  举报