Medium

题目描述

HTML 实体解析器是一个解析器,它接受 HTML 代码作为输入,并将所有特殊字符的实体替换为字符本身。

HTML 的特殊字符及其实体如下:

  • 引号:实体是 ",符号字符是 "
  • 单引号:实体是 ',符号字符是 '
  • 和号:实体是 &,符号字符是 &
  • 大于号:实体是 >,符号字符是 >
  • 小于号:实体是 &lt;,符号字符是 <
  • 斜杠:实体是 &frasl;,符号字符是 /

给定输入文本字符串给 HTML 解析器,你必须实现实体解析器。

返回用特殊字符替换实体后的文本。

示例 1:

输入:text = "&amp; is an HTML entity but &ambassador; is not."
输出:"& is an HTML entity but &ambassador; is not."
解释:解析器将把 &amp; 实体替换为 &

示例 2:

输入:text = "and I quote: &quot;...&quot;"
输出:"and I quote: \"...\""

约束条件:

  • 1 <= text.length <= 10^5
  • 字符串可能包含所有 256 个 ASCII 字符中的任何字符。

解题思路

解题思路

这道题要求我们将 HTML 实体转换为对应的字符。主要有两种解决思路:

方法一:哈希表 + 逐字符扫描

建立一个哈希表存储所有的实体映射关系,然后遍历字符串:

  • 遇到 & 字符时,尝试匹配后续的实体
  • 找到对应的分号 ; 后,检查这段内容是否为有效实体
  • 如果是有效实体则替换,否则保持原样

方法二:字符串替换

直接使用字符串的 replace 方法,按照特定顺序替换所有实体。需要注意的是,必须先替换 &amp;,因为其他实体都包含 & 字符,避免重复替换。

推荐解法

推荐使用方法一(哈希表),因为它更加直观,便于理解和维护,时间复杂度也是线性的。

实现要点:

  1. 建立实体到字符的映射表
  2. 遍历字符串,遇到 & 时尝试匹配实体
  3. 匹配成功则替换,否则保持原字符

代码实现

class Solution {
public:
    string entityParser(string text) {
        unordered_map<string, string> entities = {
            {"&quot;", "\""},
            {"&apos;", "'"},
            {"&amp;", "&"},
            {"&gt;", ">"},
            {"&lt;", "<"},
            {"&frasl;", "/"}
        };
        
        string result;
        int n = text.length();
        
        for (int i = 0; i < n; i++) {
            if (text[i] == '&') {
                bool found = false;
                for (auto& entity : entities) {
                    int len = entity.first.length();
                    if (i + len <= n && text.substr(i, len) == entity.first) {
                        result += entity.second;
                        i += len - 1;
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    result += text[i];
                }
            } else {
                result += text[i];
            }
        }
        
        return result;
    }
};
class Solution:
    def entityParser(self, text: str) -> str:
        entities = {
            "&quot;": '"',
            "&apos;": "'",
            "&amp;": "&",
            "&gt;": ">",
            "&lt;": "<",
            "&frasl;": "/"
        }
        
        result = []
        i = 0
        n = len(text)
        
        while i < n:
            if text[i] == '&':
                found = False
                for entity, char in entities.items():
                    if text[i:i+len(entity)] == entity:
                        result.append(char)
                        i += len(entity)
                        found = True
                        break
                if not found:
                    result.append(text[i])
                    i += 1
            else:
                result.append(text[i])
                i += 1
        
        return ''.join(result)
public class Solution {
    public string EntityParser(string text) {
        var entities = new Dictionary<string, string> {
            {"&quot;", "\""},
            {"&apos;", "'"},
            {"&amp;", "&"},
            {"&gt;", ">"},
            {"&lt;", "<"},
            {"&frasl;", "/"}
        };
        
        var result = new StringBuilder();
        int n = text.Length;
        
        for (int i = 0; i < n; i++) {
            if (text[i] == '&') {
                bool found = false;
                foreach (var entity in entities) {
                    int len = entity.Key.Length;
                    if (i + len <= n && text.Substring(i, len) == entity.Key) {
                        result.Append(entity.Value);
                        i += len - 1;
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    result.Append(text[i]);
                }
            } else {
                result.Append(text[i]);
            }
        }
        
        return result.ToString();
    }
}
var entityParser = function(text) {
    const entities = {
        "&quot;": '"',
        "&apos;": "'",
        "&amp;": "&",
        "&gt;": ">",
        "&lt;": "<",
        "&frasl;": "/"
    };
    
    let result = [];
    let i = 0;
    const n = text.length;
    
    while (i < n) {
        if (text[i]

复杂度分析

复杂度类型分析
时间复杂度O(n) - 其中 n 是字符串长度,每个字符最多被访问常数次
空间复杂度O(1) - 除了输出空间,只使用了常数大小的哈希表