博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
leetcode 0591. tag-validator
阅读量:6191 次
发布时间:2019-06-21

本文共 3385 字,大约阅读时间需要 11 分钟。

题目描述

给定一个表示代码片段的字符串,你需要实现一个验证器来解析这段代码,并返回它是否合法。合法的代码片段需要遵守以下的所有规则:

  1. 代码必须被合法的闭合标签包围。否则,代码是无效的。
  2. 闭合标签(不一定合法)要严格符合格式:<TAG_NAME>TAG_CONTENT</TAG_NAME>。其中,<TAG_NAME>是起始标签,</TAG_NAME>是结束标签。起始和结束标签中的 TAG_NAME 应当相同。当且仅当 TAG_NAME 和 TAG_CONTENT 都是合法的,闭合标签才是合法的。
  3. 合法的 TAG_NAME 仅含有大写字母,长度在范围 [1,9] 之间。否则,该 TAG_NAME 是不合法的。
  4. 合法的 TAG_CONTENT 可以包含其他合法的闭合标签,cdata (请参考规则7)和任意字符(注意参考规则1)除了不匹配的<、不匹配的起始和结束标签、不匹配的或带有不合法 TAG_NAME 的闭合标签。否则,TAG_CONTENT 是不合法的。
  5. 一个起始标签,如果没有具有相同 TAG_NAME 的结束标签与之匹配,是不合法的。反之亦然。不过,你也需要考虑标签嵌套的问题。
  6. 一个<,如果你找不到一个后续的>与之匹配,是不合法的。并且当你找到一个<或</时,所有直到下一个>的前的字符,都应当被解析为 TAG_NAME(不一定合法)。
  7. cdata 有如下格式:。CDATA_CONTENT 的范围被定义成 之间的字符。
  8. CDATA_CONTENT 可以包含任意字符。cdata 的功能是阻止验证器解析CDATA_CONTENT,所以即使其中有一些字符可以被解析为标签(无论合法还是不合法),也应该将它们视为常规字符。

合法代码的例子::

输入: "
This is the first line ]]>
"输出: True解释:代码被包含在了闭合的标签内:
。TAG_NAME 是合法的,TAG_CONTENT 包含了一些字符和 cdata 。即使 CDATA_CONTENT 含有不匹配的起始标签和不合法的 TAG_NAME,它应该被视为普通的文本,而不是标签。所以 TAG_CONTENT 是合法的,因此代码是合法的。最终返回True。输入: "
>> ![cdata[]] ]>]]>]]>>]
"输出: True解释:我们首先将代码分割为: start_tag|tag_content|end_tag 。start_tag -> "
"end_tag -> "
"tag_content 也可被分割为: text1|cdata|text2 。text1 -> ">> ![cdata[]] "cdata -> "]>]]>" ,其中 CDATA_CONTENT 为 "
]>"text2 -> "]]>>]"start_tag 不是 "
>>" 的原因参照规则 6 。cdata 不是 "]>]]>]]>" 的原因参照规则 7 。复制代码

不合法代码的例子::

输入: "      "输出: False解释: 不合法。如果 "" 是闭合的,那么 "" 一定是不匹配的,反之亦然。输入: "
div tag is not closed
"输出: False输入: "
unmatched <
"输出: False输入: "
closed tags with invalid tag name
123
"输出: False输入: "
unmatched tags with invalid tag name
and
"输出: False输入: "
unmatched start tag
and unmatched end tag
"输出: False复制代码

注意:

  1. 为简明起见,你可以假设输入的代码(包括提到的任意字符)只包含数字, 字母, '<','>','/','!','[',']'和' '。

代码实现

func isValid(code string) bool {	// isAvailbleTagName 返回 true, 当 code[i:j] 符合 TAG_NAME 的命名规范时	isAvailbleTagName := func(i, j int) bool {		if i > j || //code[i:] 中没有 ">"			i == j || // TAG_NAME 为 ""			i+9 < j { // TAG_NAME 长度超过 9			return false		}		for k := i; k < j; k++ {			if code[k] < 'A' || code[k] > 'Z' {				// TAG_NAME 中存在非大写字母				return false			}		}		return true	}	//store tag(start,end)	stack := make([]string, 0, 16)	for i := 0; i < len(code); {		// 所有的内容都应该在 tag 中		// 所以,除非 i == 0		// stack 中都应该至少有一个 TAG_NAME		if i > 0 && len(stack) == 0 {			return false		}		switch {		case strings.HasPrefix(code[i:], "" in code			j := i + strings.Index(code[i:], "]]>")			//not found "]]>"			if i > j {				return false			}			i = j + 3		case strings.HasPrefix(code[i:], "
" in code j := i + strings.Index(code[i:], ">") //code[i,j] is tagName if !isAvailbleTagName(i, j) { return false } tagName := code[i:j] i = j + 1 n := len(stack) //there is no start tag || tagName not match if n == 0 || stack[n-1] != tagName { return false } //start tag , end tag match,remove the tags stack = stack[:n-1] case code[i] == '<': //start tag i++ j := i + strings.Index(code[i:], ">") if !isAvailbleTagName(i, j) { return false } tagName := code[i:j] i = j + 1 stack = append(stack, tagName) default: i++ } } // len(stack) != 0 说明, TAG 没有封闭 return len(stack) == 0}复制代码

GitHub

公众号「tomorrowwu」,编程·职场·思维

转载地址:http://ftrda.baihongyu.com/

你可能感兴趣的文章
编译linux内核Documentation为man手册
查看>>
三种识别目标为移动设备的方法
查看>>
VS2008编译的程序在某些机器上运行提示“由于应用程序配置不正确,应用程序未能启动”的问题...
查看>>
C#操纵XML小结_转载
查看>>
变量的自动初始化
查看>>
Java程序员必知的8大排序
查看>>
GridView里的按钮事件
查看>>
PHP 输入两个整数n 和m,从数列1,2,3.......n 中随意取几个数, 使其和等于m ,要求将其中所有的可能组合列出来...
查看>>
Redis学习系列
查看>>
理解Android Fragmentation问题
查看>>
下MFC中对象、句柄、ID之间的区别.
查看>>
多项式相加[C++实现]
查看>>
帮助你生成放大镜效果的jQuery插件 - Melens
查看>>
asp.net MVC 约定
查看>>
处理由引用计数引起的泄漏
查看>>
javascript操作JSON
查看>>
virtualbox centos安装增强工具
查看>>
单例模式(Singleton)
查看>>
linux setenv 用法
查看>>
linux的ip配置
查看>>