6
Tag():value(""), isStart(true){}7
Tag(string value, bool isStart):value(value), isStart(isStart){}10
pair<int, bool> parseCData(string& s, int pos) {11
//cout << "Parse cdata " << s.substr(pos) << endl; 12
const string startPattern = "<![CDATA[";13
if (s.find(startPattern, pos) != pos) {17
const string endPattern = "]]>";18
int end = s.find(endPattern, pos);25
pair<Tag, bool> parseTag(string& s, int& pos) {26
//cout << "Parse tag " << s.substr(pos) << endl;28
if (pos+1 == s.length()) return {res, false};29
if (s[pos+1] == '/') {34
int end = s.find(">", pos);35
if (end == -1 || end-pos < 1 || end-pos > 9) return {res, false};36
string name = s.substr(pos, end-pos);37
for (char& c : name) {38
if (c < 'A' || c > 'Z') return {res, false};44
bool isValid(vector<Tag>& tags, int start, int end) {45
//cout << start << " " << end << endl;46
if (start > end) return true;47
if (!tags[start].isStart) return false;50
while (k <= end && c > 0) {51
if (tags[k].value == tags[start].value) {52
c += (tags[k].isStart) ? 1 : -1;56
if (c != 0) return false;58
return isValid(tags, start+1, k-1) && isValid(tags, k+1, end);61
bool isValid(string code) {63
int n = code.length();67
while (k < n && code[k] != '<') {71
if (i == 0) return false;73
if (i == n) return false;75
if (code[k+1] == '!') {76
if (i == 0) return false;77
auto cdata = parseCData(code, k);78
if (!cdata.second) return false;80
if (i == n) return false;82
auto tag = parseTag(code, i);83
if (!tag.second) return false;84
if (i == n && tag.first.isStart) return false;85
tags.push_back(tag.first);89
if (tags.size() < 2) return false;91
if (tags[0].value != tags[m-1].value || !tags[0].isStart || tags[m-1].isStart){94
return isValid(tags, 1, m-2);