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;
}
};
个性签名:时间会解决一切