Tag Validator

Problem Id: 591 Difficulty: Hard


Intuition

Solution


class Solution:
    def isValid(self, code: str) -> bool:
        if not code:
            return False

        in_meta = False
        stack = []
        name = ''

        i = 0
        while i < len(code):
            c = code[i]
            if in_meta:
                if c == '>':
                    if not name:
                        return False
                    if name[0] == '/':
                        if not stack or name[1:] != stack.pop():
                            return False
                        if not stack and i != len(code) - 1:
                            return False
                    else:
                        for x in name:
                            if x not in string.ascii_uppercase:
                                return False
                        if len(name) > 9:
                            return False
                        stack.append(name)
                    in_meta = False
                else:
                    name += c
            else:
                if c == '<':
                    if code[i:i+9] == '<![CDATA[':
                        # CDATA must be inside a tag
                        if not stack:
                            return False
                        end = code.find(']]>', i)
                        if end == -1:
                            return False
                        i = end + 2
                    else:
                        in_meta = True
                        name = ''
                else:
                    if not stack:
                        return False
            i += 1
        if in_meta or stack:
            return False
        return True