[ZOJ 1116 ] [ POJ 1911 ] A Well-Formed Problem

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章