591:标签验证器
This commit is contained in:
parent
aeab1d2064
commit
f6891202d5
172
src/main/java/leetcode/editor/cn/TagValidator.java
Normal file
172
src/main/java/leetcode/editor/cn/TagValidator.java
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
//给定一个表示代码片段的字符串,你需要实现一个验证器来解析这段代码,并返回它是否合法。合法的代码片段需要遵守以下的所有规则:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// 代码必须被合法的闭合标签包围。否则,代码是无效的。
|
||||||
|
// 闭合标签(不一定合法)要严格符合格式:<TAG_NAME>TAG_CONTENT</TAG_NAME>。其中,<TAG_NAME>是起始标签,</TAG_
|
||||||
|
//NAME>是结束标签。起始和结束标签中的 TAG_NAME 应当相同。当且仅当 TAG_NAME 和 TAG_CONTENT 都是合法的,闭合标签才是合法的。
|
||||||
|
//
|
||||||
|
// 合法的 TAG_NAME 仅含有大写字母,长度在范围 [1,9] 之间。否则,该 TAG_NAME 是不合法的。
|
||||||
|
// 合法的 TAG_CONTENT 可以包含其他合法的闭合标签,cdata (请参考规则7)和任意字符(注意参考规则1)除了不匹配的<、不匹配的起始和结束标签
|
||||||
|
//、不匹配的或带有不合法 TAG_NAME 的闭合标签。否则,TAG_CONTENT 是不合法的。
|
||||||
|
// 一个起始标签,如果没有具有相同 TAG_NAME 的结束标签与之匹配,是不合法的。反之亦然。不过,你也需要考虑标签嵌套的问题。
|
||||||
|
// 一个<,如果你找不到一个后续的>与之匹配,是不合法的。并且当你找到一个<或</时,所有直到下一个>的前的字符,都应当被解析为 TAG_NAME(不一定合法
|
||||||
|
//)。
|
||||||
|
// cdata 有如下格式:<![CDATA[CDATA_CONTENT]]>。CDATA_CONTENT 的范围被定义成 <![CDATA[ 和后续的第一个
|
||||||
|
// ]]>之间的字符。
|
||||||
|
// CDATA_CONTENT 可以包含任意字符。cdata 的功能是阻止验证器解析CDATA_CONTENT,所以即使其中有一些字符可以被解析为标签(无论合
|
||||||
|
//法还是不合法),也应该将它们视为常规字符。
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// 合法代码的例子:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//输入: "<DIV>This is the first line <![CDATA[<div>]]></DIV>"
|
||||||
|
//
|
||||||
|
//输出: True
|
||||||
|
//
|
||||||
|
//解释:
|
||||||
|
//
|
||||||
|
//代码被包含在了闭合的标签内: <DIV> 和 </DIV> 。
|
||||||
|
//
|
||||||
|
//TAG_NAME 是合法的,TAG_CONTENT 包含了一些字符和 cdata 。
|
||||||
|
//
|
||||||
|
//即使 CDATA_CONTENT 含有不匹配的起始标签和不合法的 TAG_NAME,它应该被视为普通的文本,而不是标签。
|
||||||
|
//
|
||||||
|
//所以 TAG_CONTENT 是合法的,因此代码是合法的。最终返回True。
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//输入: "<DIV>>> ![cdata[]] <![CDATA[<div>]>]]>]]>>]</DIV>"
|
||||||
|
//
|
||||||
|
//输出: True
|
||||||
|
//
|
||||||
|
//解释:
|
||||||
|
//
|
||||||
|
//我们首先将代码分割为: start_tag|tag_content|end_tag 。
|
||||||
|
//
|
||||||
|
//start_tag -> "<DIV>"
|
||||||
|
//
|
||||||
|
//end_tag -> "</DIV>"
|
||||||
|
//
|
||||||
|
//tag_content 也可被分割为: text1|cdata|text2 。
|
||||||
|
//
|
||||||
|
//text1 -> ">> ![cdata[]] "
|
||||||
|
//
|
||||||
|
//cdata -> "<![CDATA[<div>]>]]>" ,其中 CDATA_CONTENT 为 "<div>]>"
|
||||||
|
//
|
||||||
|
//text2 -> "]]>>]"
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//start_tag 不是 "<DIV>>>" 的原因参照规则 6 。
|
||||||
|
//cdata 不是 "<![CDATA[<div>]>]]>]]>" 的原因参照规则 7 。
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// 不合法代码的例子:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//输入: "<A> <B> </A> </B>"
|
||||||
|
//输出: False
|
||||||
|
//解释: 不合法。如果 "<A>" 是闭合的,那么 "<B>" 一定是不匹配的,反之亦然。
|
||||||
|
//
|
||||||
|
//输入: "<DIV> div tag is not closed <DIV>"
|
||||||
|
//输出: False
|
||||||
|
//
|
||||||
|
//输入: "<DIV> unmatched < </DIV>"
|
||||||
|
//输出: False
|
||||||
|
//
|
||||||
|
//输入: "<DIV> closed tags with invalid tag name <b>123</b> </DIV>"
|
||||||
|
//输出: False
|
||||||
|
//
|
||||||
|
//输入: "<DIV> unmatched tags with invalid tag name </1234567890> and <CDATA[[]]>
|
||||||
|
// </DIV>"
|
||||||
|
//输出: False
|
||||||
|
//
|
||||||
|
//输入: "<DIV> unmatched start tag <B> and unmatched end tag </C> </DIV>"
|
||||||
|
//输出: False
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// 注意:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// 为简明起见,你可以假设输入的代码(包括提到的任意字符)只包含数字, 字母, '<','>','/','!','[',']'和' '。
|
||||||
|
//
|
||||||
|
// Related Topics 栈 字符串
|
||||||
|
// 👍 31 👎 0
|
||||||
|
|
||||||
|
package leetcode.editor.cn;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
//591:标签验证器
|
||||||
|
public class TagValidator {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
//测试代码
|
||||||
|
Solution solution = new TagValidator().new Solution();
|
||||||
|
}
|
||||||
|
|
||||||
|
//力扣代码
|
||||||
|
//leetcode submit region begin(Prohibit modification and deletion)
|
||||||
|
class Solution {
|
||||||
|
Stack<String> stack = new Stack<>();
|
||||||
|
boolean contains_tag = false;
|
||||||
|
|
||||||
|
public boolean isValidTagName(String s, boolean ending) {
|
||||||
|
if (s.length() < 1 || s.length() > 9) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
if (!Character.isUpperCase(s.charAt(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ending) {
|
||||||
|
if (!stack.isEmpty() && stack.peek().equals(s)) {
|
||||||
|
stack.pop();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
contains_tag = true;
|
||||||
|
stack.push(s);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValidCdata(String s) {
|
||||||
|
return s.indexOf("[CDATA[") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid(String code) {
|
||||||
|
if (code.charAt(0) != '<' || code.charAt(code.length() - 1) != '>') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < code.length(); i++) {
|
||||||
|
boolean ending = false;
|
||||||
|
int closeindex;
|
||||||
|
if (stack.isEmpty() && contains_tag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (code.charAt(i) == '<') {
|
||||||
|
if (!stack.isEmpty() && code.charAt(i + 1) == '!') {
|
||||||
|
closeindex = code.indexOf("]]>", i + 1);
|
||||||
|
if (closeindex < 0 || !isValidCdata(code.substring(i + 2, closeindex))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (code.charAt(i + 1) == '/') {
|
||||||
|
i++;
|
||||||
|
ending = true;
|
||||||
|
}
|
||||||
|
closeindex = code.indexOf('>', i + 1);
|
||||||
|
if (closeindex < 0 || !isValidTagName(code.substring(i + 1, closeindex), ending)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = closeindex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stack.isEmpty() && contains_tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//leetcode submit region end(Prohibit modification and deletion)
|
||||||
|
|
||||||
|
}
|
85
src/main/java/leetcode/editor/cn/TagValidator.md
Normal file
85
src/main/java/leetcode/editor/cn/TagValidator.md
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<p>给定一个表示代码片段的字符串,你需要实现一个验证器来解析这段代码,并返回它是否合法。合法的代码片段需要遵守以下的所有规则:</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>代码必须被<strong>合法的闭合标签</strong>包围。否则,代码是无效的。</li>
|
||||||
|
<li><strong>闭合标签</strong>(不一定合法)要严格符合格式:<code><TAG_NAME>TAG_CONTENT</TAG_NAME></code>。其中,<code><TAG_NAME></code>是起始标签,<code></TAG_NAME></code>是结束标签。起始和结束标签中的 TAG_NAME 应当相同。当且仅当 TAG_NAME 和 TAG_CONTENT 都是合法的,闭合标签才是<strong>合法的</strong>。</li>
|
||||||
|
<li><strong>合法的</strong> <code>TAG_NAME</code> 仅含有<strong>大写字母</strong>,长度在范围 [1,9] 之间。否则,该 <code>TAG_NAME</code> 是<strong>不合法的</strong>。</li>
|
||||||
|
<li><strong>合法的</strong> <code>TAG_CONTENT</code> 可以包含其他<strong>合法的闭合标签</strong>,<strong>cdata</strong> (请参考规则7)和任意字符(注意参考规则1)<strong>除了</strong>不匹配的<code><</code>、不匹配的起始和结束标签、不匹配的或带有不合法 TAG_NAME 的闭合标签。否则,<code>TAG_CONTENT</code> 是<strong>不合法的</strong>。</li>
|
||||||
|
<li>一个起始标签,如果没有具有相同 TAG_NAME 的结束标签与之匹配,是不合法的。反之亦然。不过,你也需要考虑标签嵌套的问题。</li>
|
||||||
|
<li>一个<code><</code>,如果你找不到一个后续的<code>></code>与之匹配,是不合法的。并且当你找到一个<code><</code>或<code></</code>时,所有直到下一个<code>></code>的前的字符,都应当被解析为 TAG_NAME(不一定合法)。</li>
|
||||||
|
<li>cdata 有如下格式:<code><![CDATA[CDATA_CONTENT]]></code>。<code>CDATA_CONTENT</code> 的范围被定义成 <code><![CDATA[</code> 和<strong>后续的第一个</strong> <code>]]></code>之间的字符。</li>
|
||||||
|
<li><code>CDATA_CONTENT</code> 可以包含<strong>任意字符</strong>。cdata 的功能是阻止验证器解析<code>CDATA_CONTENT</code>,所以即使其中有一些字符可以被解析为标签(无论合法还是不合法),也应该将它们视为<strong>常规字符</strong>。</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p><strong>合法代码的例子:</strong></p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<strong>输入:</strong> "<DIV>This is the first line <![CDATA[<div>]]></DIV>"
|
||||||
|
|
||||||
|
<strong>输出:</strong> True
|
||||||
|
|
||||||
|
<strong>解释:</strong>
|
||||||
|
|
||||||
|
代码被包含在了闭合的标签内: <DIV> 和 </DIV> 。
|
||||||
|
|
||||||
|
TAG_NAME 是合法的,TAG_CONTENT 包含了一些字符和 cdata 。
|
||||||
|
|
||||||
|
即使 CDATA_CONTENT 含有不匹配的起始标签和不合法的 TAG_NAME,它应该被视为普通的文本,而不是标签。
|
||||||
|
|
||||||
|
所以 TAG_CONTENT 是合法的,因此代码是合法的。最终返回True。
|
||||||
|
|
||||||
|
|
||||||
|
<strong>输入:</strong> "<DIV>>> ![cdata[]] <![CDATA[<div>]>]]>]]>>]</DIV>"
|
||||||
|
|
||||||
|
<strong>输出:</strong> True
|
||||||
|
|
||||||
|
<strong>解释:</strong>
|
||||||
|
|
||||||
|
我们首先将代码分割为: start_tag|tag_content|end_tag 。
|
||||||
|
|
||||||
|
start_tag -> <strong>"<DIV>"</strong>
|
||||||
|
|
||||||
|
end_tag -> <strong>"</DIV>"</strong>
|
||||||
|
|
||||||
|
tag_content 也可被分割为: text1|cdata|text2 。
|
||||||
|
|
||||||
|
text1 -> <strong>">> ![cdata[]] "</strong>
|
||||||
|
|
||||||
|
cdata -> <strong>"<![CDATA[<div>]>]]>"</strong> ,其中 CDATA_CONTENT 为 <strong>"<div>]>"</strong>
|
||||||
|
|
||||||
|
text2 -> <strong>"]]>>]"</strong>
|
||||||
|
|
||||||
|
|
||||||
|
start_tag <strong>不</strong>是 <strong>"<DIV>>>"</strong> 的原因参照规则 6 。
|
||||||
|
cdata <strong>不</strong>是 <strong>"<![CDATA[<div>]>]]>]]>"</strong> 的原因参照规则 7 。
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p><strong>不合法代码的例子:</strong></p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<strong>输入:</strong> "<A> <B> </A> </B>"
|
||||||
|
<strong>输出:</strong> False
|
||||||
|
<strong>解释:</strong> 不合法。如果 "<A>" 是闭合的,那么 "<B>" 一定是不匹配的,反之亦然。
|
||||||
|
|
||||||
|
<strong>输入:</strong> "<DIV> div tag is not closed <DIV>"
|
||||||
|
<strong>输出:</strong> False
|
||||||
|
|
||||||
|
<strong>输入:</strong> "<DIV> unmatched < </DIV>"
|
||||||
|
<strong>输出:</strong> False
|
||||||
|
|
||||||
|
<strong>输入:</strong> "<DIV> closed tags with invalid tag name <b>123</b> </DIV>"
|
||||||
|
<strong>输出:</strong> False
|
||||||
|
|
||||||
|
<strong>输入:</strong> "<DIV> unmatched tags with invalid tag name </1234567890> and <CDATA[[]]> </DIV>"
|
||||||
|
<strong>输出:</strong> False
|
||||||
|
|
||||||
|
<strong>输入:</strong> "<DIV> unmatched start tag <B> and unmatched end tag </C> </DIV>"
|
||||||
|
<strong>输出:</strong> False
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p><strong>注意:</strong></p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>为简明起见,你可以假设输入的代码(包括提到的<strong>任意字符</strong>)只包含<code>数字</code>, <font color="#c7254e" face="Menlo, Monaco, Consolas, Courier New, monospace"><span style="background-color:#f9f2f4; font-size:12.6px">字母</span></font>, <code>'<'</code>,<code>'>'</code>,<code>'/'</code>,<code>'!'</code>,<code>'['</code>,<code>']'</code>和<code>' '</code>。</li>
|
||||||
|
</ol>
|
||||||
|
<div><div>Related Topics</div><div><li>栈</li><li>字符串</li></div></div>\n<div><li>👍 31</li><li>👎 0</li></div>
|
Loading…
Reference in New Issue
Block a user