表示数值的字符串(有限状态自动机与搜索)
文章目录
- 题目
- 思路一
- 代码一
- 思路二
- 代码二
题目
思路一
考察有限状态自动机(参考jyd):
字符类型:
空格 「 」、数字「 0—9 」 、正负号 「 ± 」 、小数点 「 . 」 、幂符号 「 eE 」 。
状态定义:
按照字符串从左到右的顺序,定义以下 9 种状态:
- 开始的空格
- 幂符号前的正负号
- 小数点前的数字
- 小数点、小数点后的数字
- 当小数点前为空格时,小数点、小数点后的数字
- 幂符号
- 幂符号后的正负号
- 幂符号后的数字
- 结尾的空格
结束状态:
合法的结束状态有 2, 3, 7, 8 。
算法流程:
初始化:
- 状态转移表 maps : 设 maps[i] ,其中 i 为所处状态(9种之一), maps[i] 使用哈希表存储可转移至的状态。键值对 (key, value) 含义:若此时的字符是 key ,则可从状态 i 转移至状态 value 。
- 当前状态 p : 起始状态初始化为 p = 0 。
状态转移循环: 遍历字符串 s 的每个字符 c 。
记录字符类型 t : 分为四种情况。
- 当 c 为正负号时,执行
t = 's'
; - 当 c 为数字时,执行
t = 'd'
; - 当 c 为 e , E 时,执行
t = 'e'
; - 当 c 为 . , 空格 时,执行
t = c
(即用字符本身表示字符类型); - 否则,执行 t = ‘?’ ,代表为不属于判断范围的非法字符,后续直接返回 false。
- 当 c 为正负号时,执行
终止条件: 若字符类型 t 不在哈希表 maps[p] 中,说明无法转移至下一状态,因此直接返回 False 。
状态转移: 状态 p 转移至
maps[p][t]
。
返回值: 跳出循环后,若状态
p∈2,3,7,8
,说明结尾合法,返回 True ,否则返回 False 。
再详细说一下状态转移表的作用(下面代码部分的注释中有结合实例进行详解):
- 处于第 i 行表明此时遍历到的字符是第 i+1 种状态(可以对照上文的状态定义)
- 那么我下一个字符可以是第 i 行中的各个 key 对应的字符。
- 如果某字符没有写进第 i 行,表示 i+1 状态的下一个字符不应是某字符
复杂度分析:
- 时间复杂度 O(N) : 其中 N 为字符串 s 的长度,判断需遍历字符串,每轮状态转移的使用 O(1) 时间。
- 空间复杂度 O(1) : maps 和 p 使用常数大小的额外空间。
代码一
class Solution {public:bool isNumber(string s) {vector<map<char,int>> maps = {// 状态转移表
// 以第一行为例,状态转移表的含义为:
// 开始的空格其下一个字符可以继续是空格,也可以是符号、数字、小数点,
// 但不可是第0行不存在的e。
// 也就是为了保证字符串是数值,空格后面不能直接跟一个幂符号。{{' ', 0}, {'s', 1}, {'d', 2}, {'.', 4}}, // 开始的空格{{'d', 2}, {'.', 4}}, // 幂符号前的正负号{{'d', 2}, {'.', 3}, {'e', 5}, {' ', 8}}, // 小数点前的数字{{'d', 3}, {'e', 5}, {' ', 8}}, // 小数点、小数点后的数字{{'d', 3}}, // 当小数点前为空格时,小数点、小数点后的数字{{'s', 6}, {'d', 7}}, // 幂符号{{'d', 7}}, // 幂符号后的正负号{{'d', 7}, {' ', 8}}, // 幂符号后的数字{{' ', 8}} // 结尾的空格};int p = 0; //起始状态char t;for(char c : s) {if(c >= '0' && c <= '9') t = 'd';else if(c == '+' || c == '-') t = 's';else if(c == 'e' || c == 'E') t = 'e';else if(c == '.' || c == ' ') t = c;else t = '?';if(maps[p].find(t) == maps[p].end()) return false;p = maps[p][t];}return p == 2 || p == 3 || p == 7 || p == 8;}
};
思路二
用 bool 类型变量 ret 存储搜索过程中的结果,整个搜索过程如下:
- 过滤首部空格
- 过滤正负号,紧接着检查是否有数字
- 遇到第一个不是数字的字符,应为
'.'
或者e
'.'
的后面可以有e
,但e
的后面不能有'.'
,所以先处理'.'
再处理e
'.'
前面可以什么都没有,后面也可以什么都没有,只要有一边有数据就行e
的前后必须都要有数据,并且后面可以存在正负号,所以需要过滤正负号- 过滤尾部空格
- 检查 ret 状态以及是否已经遍历完字符串
关于第8点检查是否已经遍历完字符串:
因为如果字符串是数值,尾部空格应该是字符串的末尾部分倒数几个字符,空格完了字符串应该也就结束了。如果过滤完了尾部空格还有字符,说明该字符串不是数值。
代码二
class Solution {public:bool scanDigit(string s, int& i){int count = i;while(i != s.size()){if(isdigit(s[i]))++i;elsebreak;}return i > count;//如果数据中没有一个数字,则直接返回false,有则返回true}bool scanSign(string s, int& i){if(i < s.size() && s[i] == '+' || s[i] == '-'){++i;}//过滤正负号return scanDigit(s, i);}bool isNumber(string s) {if(s.empty())return false;int i = 0;while(s[i] == ' ')++i;//过滤首部空格bool ret = scanSign(s, i);//第一遍搜索,先走完.或者e前的所有数字//.的后面可以有e,但e的后面不能有.,所以先处理.再处理eif(i < s.size() && s[i] == '.'){ret = scanDigit(s, ++i) || ret;//.前面可以什么都没有,后面也可以什么都没有,只要有一边有数据就行}if(i < s.size() && (s[i] == 'e' || s[i] == 'E')){ret = scanSign(s, ++i) && ret;//e的前后必须都要有数据,并且e后面可以存在正负号,所以需要过滤正负号}while(s[i] == ' ')++i;//因为空格只能出现在末尾和首部,过滤空格return ret && (i == s.size());//当e后面有数据,并且字符串全部走完,说明数据成立}
};
表示数值的字符串(有限状态自动机与搜索)相关推荐
- 有限状态自动机java实现_用java开发编译器之:Thompson构造,将正则表达式转换为有限状态自动机...
阅读博客的朋友可以到我的网易云课堂中,通过视频的方式查看代码的调试和执行过程: 上一节,我们通过代码,实现了一个有限状态自动机,并将其应用于对整形和浮点数的识别.构造有限状态自动机,并驱动它,从而实现 ...
- 剑指offer之表示数值的字符串
题目 请实现一个函数用来判断字符串是否表示数值(包括整数和小数).例如,字符串"+100","5e2","-123","3.141 ...
- 用java开发编译器之:Thompson构造,将正则表达式转换为有限状态自动机
阅读博客的朋友可以到我的网易云课堂中,通过视频的方式查看代码的调试和执行过程: http://study.163.com/course/courseMain.htm?courseId=10028300 ...
- 第十二篇:形式语言理论与有限状态自动机
目录 我们到目前已经介绍了什么? 形式语言理论 为什么要去做这个事情 ? 例子 超越会员问题-- 大纲 常规语言/正则语言 例子重现 正则语言的特性 有限状态接受器 样例 派生形态学 形态学 FSA ...
- 【Codeforces 506E】Mr.Kitayuta’s Gift【BZOJ 4214】黄昏下的礼物 dp转有限状态自动机+矩阵乘法优化...
神题-- 胡乱讲述一下思维过程-- 首先,读懂题. 然后,转化问题为构造一个长度为|T|+n的字符串,使其内含有T这个子序列. 之后,想到一个简单的dp.由于是回文串,我们就增量构造半个回文串,设f( ...
- 一.正则表达式转换为有限状态自动机:正则表达式转NFA
原文:https://study.163.com/course/courseMain.htm?courseId=1002830012 一.有限状态自动机的分类 有限状态自动机,其实可以分成两类.第一类 ...
- python 数值型字符串实现四舍五入 decimal_Python将科学计数法数值转换为指定精度浮点数...
Python将科学计数法数值转换为指定精度浮点数 In [20]:money = 1190000.0 In [21]: traded_maket_value = 13824000000 In [22] ...
- 剑指offer:面试题20. 表示数值的字符串
题目:表示数值的字符串 请实现一个函数用来判断字符串是否表示数值(包括整数和小数).例如,字符串"+100"."5e2"."-123".&q ...
- (剑指Offer)面试题54:表示数值的字符串
题目: 请实现一个函数用来判断字符串是否表示数值(包括整数和小数).例如,字符串"+100","5e2","-123","3.14 ...
最新文章
- 计算机操作培训主持词,魅力女性沙龙会主持词文稿.docx
- 转 Hystrix入门指南 Introduction
- php调mysql接口头文件_php基础系列:PHP连接MySQL数据库用到的三种API
- linux交换分区的文件格式为,LINUX的交换分区或交换文件SWAP的查看与维护
- python函数返回none_Python 函数默认返回None的原因
- java基础面试题之:普通类和抽象类有哪些区别?
- mysql1045错误解读_谈谈MYSQL ERROR 1045 错误的解决办法!
- pro android学习笔记,【转】Pro Android学习笔记(一):Android 平台 2013.6.4
- 阿里云公布IP地理位置库抄袭调查结果;华为云电脑8月16日将停止服务和运营;Chrome 92发布|极客头条...
- 来到深圳奋斗的这些年(不断更新!)
- 如何给Exadata数据库一体机打补丁patching图解
- Android实战开发-Kotlin教程(入门篇 1.0)
- Java 就业培训教程 第二章读书笔记啊
- 简单易懂的贝叶斯公式
- C语言实现矩阵卷积运算
- matlab gui制作,MATLAB GUI制作教程
- 在线作图|2分钟绘制一张相关性桑基图
- C语言入门题库——求2+22+222+......+22222的值
- 热释电人体感应红外报警器设计 - 没人取消报警
- App Store Review Guidelines中文版-上部
热门文章
- mysql数据库开启远程连接_安装MySQL数据库并开启远程访问
- java8 list 去重_Java8-Stream在集合中的8种应用案例
- 【转】17.Qt界面布局管理详解
- 24组合模式(Composite Pattern)
- [你必须知道的.NET]第十六回:深入浅出关键字---using全接触
- 【转】3.2SharePoint服务器端对象模型 之 访问文件和文件夹(Part 2)
- 【转】2.3SharePoint服务器端对象模型 之 访问网站和列表数据(Part 3)
- mysql系列:加深对脏读、脏写、可重复读、幻读的理解
- 查找字符位置_如何使用find函数和search函数精确查找字符
- CCIE-LAB-第一篇-教学导入环境