← Home

1410. HTML Entity Parser

LeetCode article · C++ solution
Website made by wuisabel-gif · Original C++ code by keineahnung2345
trieC++Markdown
141

A good way into this one is to ask: what do we need to remember so we never redo work blindly? For 1410. HTML Entity Parser, the solution in this repository is mainly a trie solution.

Guide

What?

The first job is to translate the English prompt into state, transition, and stopping conditions. Instead of trying to be clever immediately, read the code as a sequence of questions:

  • What state are we keeping?
  • How do we move from one state to the next?
  • When do we know the answer is already determined?

For this file, the main tools are: trie.

The notes already sitting in the source point us in the right direction:

  • Once accepted answer

Guide

When?

This pattern shows up when the brute force version has too many repeated checks, too many possible branches, or too much bookkeeping to do by hand. The accepted code reduces that pressure by storing exactly the information that remains useful later.

The important function names to track are entityParser, add.

Guide

Why?

The win comes from making each line carry responsibility: store the useful state, discard the rest, keep moving.

  • A map keeps the lookup side cheap; the code pays a little memory to avoid repeated searching.
  • Substring checks are convenient but not free, so they are part of the real complexity story.
  • The final return is not magic; it is the invariant after the loops or recursion have finished doing their accounting.

Guide

How?

Walk through the solution in this order:

  1. Read the setup variables first.
  2. Follow the main loop or recursive helper next.
  3. Watch where invalid states get skipped.
  4. Check which value survives to the return statement.

The most important competitive-programming habit here is to trust the invariant. Once the invariant is right, the loops become much less scary.

Guide

Complexity

  • Time: O(n) to O(n log n), depending on the dominant loop or data structure operation
  • Space: O(n) in the usual case for auxiliary containers or recursion

Guide

C++ Solution

Your submission

The accepted solution

solution.cpp
01//Once accepted answer
02/*
03151 / 154 test cases passed.
04Input: "&"
05Output: "&"
06Expected: "&"
07*/
08//Runtime: 1204 ms
09//Memory Usage: 16.4 MB
10class Solution {
11public:
12    string entityParser(string text) {
13        map<string, string> entityMap = {
14            {"&quot;" , "\""},
15            {"&apos;",  "'"}, 
16            {"&amp;" , "&"}, 
17            {"&gt;" , ">"}, 
18            {"&lt;" , "<"}, 
19            {"&frasl;" , "/"}
20            };
21        
22        for(auto it = entityMap.begin(); it != entityMap.end(); it++){
23            size_t pos = 0;
24
25            while((pos = text.find(it->first, pos)) != string::npos){
26                text.replace(pos, (it->first).length(), it->second);
27            }
28        }
29        
30        return text;
31    }
32};
33
34//Two pointer
35//https://leetcode.com/problems/html-entity-parser/discuss/575416/C%2B%2B-two-pointers-O(n)-or-O(1)
36//Runtime: 196 ms, faster than 93.55% of C++ online submissions for HTML Entity Parser.
37//Memory Usage: 16.3 MB, less than 100.00% of C++ online submissions for HTML Entity Parser.
38class Solution {
39public:
40    string entityParser(string text) {
41        map<string, char> entityMap = {
42            {"&quot;" , '\"'},
43            {"&apos;",  '\''}, 
44            {"&amp;" , '&'}, 
45            {"&gt;" , '>'}, 
46            {"&lt;" , '<'}, 
47            {"&frasl;" , '/'}
48            };
49        
50        int slow = 0;
51        map<string, char>::iterator it;
52        
53        //it ends when we examine the whole string using "fast"
54        for (int fast = 0, lastAnd = 0; fast < text.size(); ++fast, ++slow) {
55            text[slow] = text[fast];
56            
57            if (text[slow] == '&')
58                lastAnd = slow; //will be used when we meet ';'
59            
60            if (text[slow] == ';') {
61                // cout << text << " " << lastAnd << " " << slow << endl;
62                if((it = entityMap.find(text.substr(lastAnd, slow - lastAnd + 1))) != entityMap.end()){
63                    //suppose we meet "&gt;", now we will write '>' in the position of '&'
64                    slow = lastAnd;
65                    //modify the "text" in-place
66                    text[slow] = it->second;
67                    
68                }
69                /*an '&' can be used only once, 
70                here we move lastAnd forward to 
71                avoid the last '&' be used next time
72                Example: "&amp;amp;"
73                */
74                lastAnd = slow + 1;
75            }
76        }
77        
78        //now "slow" is the index just after last write
79        text.resize(slow);
80        return text;
81    }
82};
83
84//Two pointer + Trie
85//https://leetcode.com/problems/html-entity-parser/discuss/575416/C%2B%2B-two-pointers-O(n)-or-O(1)
86//Runtime: 180 ms, faster than 95.80% of C++ online submissions for HTML Entity Parser.
87//Memory Usage: 18 MB, less than 100.00% of C++ online submissions for HTML Entity Parser.
88//time: O(N)
89class TrieNode{
90public:
91    vector<TrieNode*> children;
92    char mappedSymbol;
93    
94    TrieNode(){
95        children = vector<TrieNode*>(26, nullptr);
96        mappedSymbol = '\0';
97    }
98};
99
100class Trie{
101public:
102    TrieNode* root;
103    
104    Trie(){
105        root = new TrieNode();
106    };
107    
108    void add(string word, char symbol){
109        TrieNode* cur = root;
110        for(char c : word){
111            if(cur->children[c-'a'] == nullptr){
112                cur->children[c-'a'] = new TrieNode();
113            }
114            cur = cur->children[c-'a'];
115        }
116        //the trie contains the info mapping by itself
117        cur->mappedSymbol = symbol;
118    };
119    
120    char search(string word){
121        TrieNode* cur = root;
122        for(char c : word){
123            if(cur->children[c-'a'] == nullptr)
124                return '\0';
125            cur = cur->children[c-'a'];
126        }
127        return cur->mappedSymbol;
128    };
129};
130
131class Solution {
132public:
133    string entityParser(string text) {
134        map<string, char> entityMap = {
135            {"&quot;" , '\"'},
136            {"&apos;",  '\''}, 
137            {"&amp;" , '&'}, 
138            {"&gt;" , '>'}, 
139            {"&lt;" , '<'}, 
140            {"&frasl;" , '/'}
141            };
142        
143        int slow = 0;
144        map<string, char>::iterator it;
145        Trie* trie = new Trie();
146        
147        for(it = entityMap.begin(); it != entityMap.end(); it++){
148            //remove key's head's & and tail's ;
149            // cout << it->first.substr(1, it->first.size()-2) << endl;
150            trie->add(it->first.substr(1, it->first.size()-2), it->second);
151        }
152        
153        for (int fast = 0, lastAnd = 0; fast < text.size(); ++fast, ++slow) {
154            text[slow] = text[fast];
155            
156            if (text[slow] == '&')
157                lastAnd = slow;
158            
159            if (text[slow] == ';') {
160                // cout << text << " " << lastAnd << " " << slow << endl;
161                char c;
162                if((c = trie->search(text.substr(lastAnd+1, slow-1-lastAnd))) != '\0'){
163                    // cout << text.substr(lastAnd+1, slow-1-lastAnd) << ", " << c << endl;
164                    slow = lastAnd;
165                    text[slow] = c;
166                    
167                }
168                lastAnd = slow + 1;
169            }
170        }
171        
172        text.resize(slow);
173        return text;
174    }
175};

Cost

Complexity

Time
O(n) to O(n log n), depending on the dominant loop or data structure operation
Dominated by the main traversal, recursion, or data-structure operations in the code.
Space
O(n) in the usual case for auxiliary containers or recursion
Auxiliary state plus the answer structure where the problem requires one.