ZOJ:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1116
題目大意:
(對XML沒有了解,只是按照字面意思理解了一下題意)
<name>與</name>這樣有起始結束聲明的,name稱爲tag
<order/>是empty element, 不需要end-tag
第一行<?xml version="1.0"?>不算文檔的element
<zip-code format="PLUS4">10001-0001</zip-code>這裏的format是zip-code的屬性
一個well-formed document要滿足下面幾條:
1、只有一個element不嵌套在別的element裏,例如例子中的"customer"
2、嵌套正確,不是<order/>那樣的,如<name>與</name>要完整配對嵌套
3、如<name>與</name>這樣的聲明名字要配對
4、一個tag最多一個屬性
5、不遞歸調用,如address element裏不能調用address
6、有名字的屬性,比如上面的format,要有對應的值
注意大小寫不同,如<Address>和<address>應該認爲是不同的
輸入:
每組數據第一行是 "<?xml version="1.0"?>"。
"<?end?>" 表示全部輸入的結束(只是在本題中用來標記輸入結束)
輸入保證:
"<?xml version="1.0"?>"會且僅會在第一行出現
element和屬性只用數字、字母和短線"-"表示
XML註釋不出現
屬性的值一定會放在“”裏
輸出
"well-formed"或者"non well-formed"
解題思路:
字符串處理,主要用到棧和集合。
每次讀入到”<“的時候,開始讀取tag和attribute,同時判斷<>裏頭的內容有沒有問題,比如"/"出現的位置和次數有沒有問題,屬性的表達有沒有問題等。之後就只要進行一些判斷即可。下面是針對well-formed document的各條件的解決方法:
1、針對“只有一個element不嵌套在別的element裏,例如例子中的"customer" ”
設置bool root=false; 當棧空且有入棧操作時root=true;當root=true且在棧空情況下有入棧操作時返回non well-formed
2、針對“嵌套正確,不是<order/>那樣的,如<name>與</name>要完整配對嵌套”
棧,非類似<order/>時入棧,入棧忽略屬性,出棧時與棧頂元素
3、針對“如<name>與</name>這樣的聲明名字要配對”
同上
4、針對“一個tag最多一個屬性”
若在<>裏讀到""(輸入保證如果有屬性,其值一定包括在""裏), 則之後如果再出現非空字符,返回non well-formed
5、針對“不遞歸調用,如address element裏不能調用address”
設置set<string>類型,存放棧內元素,入棧前判斷set裏是否有相同tag,如果是,返回non well-formed
6、針對“有名字的屬性,比如上面的format,要有對應的值”
在<>內如果讀到空格,空格後面有字符,則必須有緊跟的="XXX"
源代碼:
又吐血了……”狗狗搞完40題“裏的代碼又好短,淚奔了,爲什麼每次寫蘑菇題我都要寫得很長╮(╯▽╰)╭
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <string>
#include <set>
#include <stack>
#include <iostream>
#include <algorithm>
using namespace std;
#define ERROR non=true;return
set<string> used;
stack<string> s;
bool non, root;
bool gettag(char* &ch, string &tag, bool &end, bool &empty)
// 讀到"<"觸發gettag, 函數結束後">"已讀過
{
int p1, p2, p3, p4;
string attribute;
end=false, empty=false;
tag=attribute="";
ch++; //get tag
if (*ch=='/'){end=true;ch++;}
while (isalnum(*ch) || *ch=='-')
{
tag+=*ch;
ch++;
}
while (isspace(*ch)) ch++;
if (*ch=='>') //end of tag?
return 1;
if (*ch=='/')
{
int cal=0;
ch++;
while (*ch!='>'){cal++;ch++;}
if (cal>0) return -2;
if (end) return -1;
else empty=true;
}
while (isalnum(*ch) || *ch=='-' || *ch=='.' || *ch=='\"' || *ch=='=') //get attribute
{
attribute+=*ch;
ch++;
}
if (attribute.length()>0)
{
p1=attribute.find("=", 0); if (p1==-1) return -3;
p2=attribute.find("\"", 0); if (p2<p1) return -4;
p2=attribute.find("\"", p1+1); if (p2==-1) return -5;
p3=attribute.find("\"", p2+1); if (p3==-1 || p3==p2+1) return -6; //empty value
p4=attribute.find("\"", p3+1); if (p4!=-1) return -7; //extra "
p4=attribute.find("=", p1+1); if (p4!=-1) return -8; //extra =
}
while (isspace(*ch)) ch++;
if (*ch=='>') return 1;
if (*ch=='/')
{
int cal=0;
ch++;
while (*ch!='>'){cal++;ch++;}
if (cal>0) return -10;
if (end) return -9;
else empty=true;
}
while (*ch!='>'){
ch++;
if (!isspace(*ch) && *ch!='>') return -11;
}
return 1;
}
void solve(char *ch)
{
bool end, empty;
string tag;
int tmp;
while (!non && *ch!='\0')
{
if (*ch=='<')
{
tmp=gettag(ch, tag, end, empty);
if (tmp==1)
{
if (end && empty){
ERROR;
}
if (empty && used.count(tag)>0){
ERROR;
}
else if (!empty && !end)
{
if (used.count(tag)>0){
ERROR;
}
if (s.empty())
{
if (root){ERROR;}
else root=true;
}
used.insert(tag);
s.push(tag);
}
else if (!empty && end)
{
if (s.empty() || s.top()!=tag){
ERROR;
}
used.erase(tag);
s.pop();
}
}
else{ERROR;}
}
else ch++;
}
}
int main()
{
string tag, attribute;
bool firstdata=true;
bool end, empty;
char buf[65536];
do{
while (gets(buf)!=NULL && strcmp(buf, "<?xml version=\"1.0\"?>")!=0
&& strcmp(buf, "<?end?>\n")!=0)
{
solve(buf);
}
if (strcmp(buf, "<?xml version=\"1.0\"?>")==0)
{
if (!firstdata)
{
if (non || !s.empty()) printf("non well-formed\n");
else printf("well-formed\n");
}
else firstdata=false;
non=false;
root=false;
used.clear();
while (!s.empty()) s.pop();
}
}while (strcmp(buf, "<?end?>")!=0);
if (non || !s.empty()) printf("non well-formed\n");
else printf("well-formed\n");
return 0;
}