有穷自动机解决字符问题
leetCode 第八题
8. 字符串转换整数 (atoi)
请你来实现一个 myAtoi(string s)
函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi
函数)。
函数 myAtoi(string s)
的算法如下:
- 读入字符串并丢弃无用的前导空格
- 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
- 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
- 将前面步骤读入的这些数字转换为整数(即,“123” -> 123, “0032” -> 32)。如果没有读入数字,则整数为
0
。必要时更改符号(从步骤 2 开始)。 - 如果整数数超过 32 位有符号整数范围
[−231, 231 − 1]
,需要截断这个整数,使其保持在这个范围内。具体来说,小于−231
的整数应该被固定为−231
,大于231 − 1
的整数应该被固定为231 − 1
。 - 返回整数作为最终结果。
注意:
- 本题中的空白字符只包括空格字符
' '
。 - 除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。
题目不难,Corner case比较多,最近在学编译原理,所以尝试用自动机的思想去理解这个题目。代码中加了很多注释,希望下次再打开我还能看明白吧。
import java.util.*;
public class Test8 {
int res = 0;
public int myAtoi(String s) {
if(s.length()==0||s.isEmpty()) {
return res;
}
Automaton automaton = new Automaton();
int length = s.length();
for(int i = 0; i < length;++i) {
automaton.get(s.charAt(i));
}
res = (int) (automaton.sign*automaton.ans);
return res;
}
}
class Automaton{
public int sign = 1;
public long ans = 0;
private String state = "start";
private Map<String,String[]> table = new HashMap<String,String[]>(){{
//将自动机中的各种状态装入到map中去
put("start",new String[] {"start","signed","in_number","end"});
//其中的状态分别是 sign符号转换态、in_number转换态以及end终止态
put("signed", new String[]{"end", "end", "in_number", "end"});
put("in_number", new String[]{"end", "end", "in_number", "end"});
put("end", new String[]{"end", "end", "end", "end"});
}};
/**
* 对给定的一个字符 然后转换成一个long
* @param c
*/
public void get(char c) {
//这里的state表示之前存入map中的状态,分别是四种状态
//table.get获取的是一个String数组,用get_col方法来完成获取到字符串数组中的下标功能
state = table.get(state)[get_col(c)];
//如果自动机的状态是in_number,接下来就将这个字符转为数字然后*10累加起来
if("in_number".equals(state)) {
//数字字符的ASCII码-0字符的ascii码后,得到的就是个数字。
ans = ans*10+c-'0';
//判断数字是否越界,此处的sign是个标识,用来管理符号的正负
ans = sign == 1 ? Math.min(ans, (long) Integer.MAX_VALUE) : Math.min(ans, -(long)Integer.MIN_VALUE);
}else if("signed".equals(state)) {
sign = c == '+'?1:-1;
}
}
/**
* 此函数用来获取字符串数组的下标,并且将corner case与map绑定起来
* 开头为空,对应着start态
* 为+ 或者 - 则对应着signed
* @param c
* @return
*/
public int get_col(char c) {
if(c==' ') {
return 0;
}
if(c == '+' || c == '-') {
return 1;
}
//isDigit函数是用来判断一个字符是否为数字
if(Character.isDigit(c)) {
return 2;
}
return 3;
}
}
定风波
把酒花前欲问君。世间何计可留春。纵使青春留得住。
虚语。无情花对有情人。
任是好花须落去。自古。红颜能得几时新。暗想浮生何时好。
唯有。清歌一曲倒金尊。