Fork me on GitHub

HDU 4782 Beautiful Soup --模拟

题意: 将一些分散在各行的HTML代码整理成标签树的形式。

解法: 模拟,具体见代码的讲解。 开始没考虑 '\t' 。。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
using namespace std;

string S,tmp,pre;

int main()
{
    int t,i,j,cs = 1;
    scanf("%d",&t);
    getchar();
    pre = "";
    while(t--)
    {
        S = "";
        int fir = 1;    //是否是第一个子串
        while(1)
        {
            getline(cin,tmp,'\n');
            if(fir) { tmp = pre + tmp; S = S + tmp; fir = 0; }  //如果是第一个子串,看有没有遗留在前面case的部分
            else S = S + " " + tmp;
            int ls = S.length();
            int lt = tmp.length();
            int tag = 1;
            for(i=0;i<=lt-7;i++)          //读入
            {
                if(tmp.substr(i,7) == "</html>")
                {
                    S = S.substr(0,ls-lt+i+7);
                    pre = tmp.substr(i+7,lt-i-7);
                    tag = 0;
                    break;
                }
            }
            if(!tag) break;
        }
        int len = S.length(), deep = 0;
        printf("Case #%d:\n",cs++);
        for(i=0;i<len;i++) if(S[i] == '\t') S[i] = ' ';  //把Tab转换掉
        //cout<<"S = "<<S<<endl;
        for(i=0;i<len;i++)
        {
            if(S[i] == '<')                        //标签部分
            {
                if(S[i+1] != '/') deep++;          // 1.开标签,深度+
                else              deep--;          // 2.闭标签,深度-
                for(j=0;j<deep-(S[i+1]=='/'?0:1);j++) printf(" ");   //如果是闭标签,不用减一个空格,否则要建一个空格输出,因为开始就deep++了
                if(S[i+1] != '/')                  //如果是类似 <hr/> 的空标签,deep--抵消开标签的deep++
                {
                    for(j=i;S[j]!='>' && j < len;j++);
                    if(S[j-1] == '/') deep--; 
                }
                for(i;S[i]!='>';i++) cout<<S[i];   //输出标签内容
                cout<<">"<<endl;
            }
            else            //正文部分,空格地方小心处理
            {
                string buf = "";                        //缓冲部分
                int letter = 0;
                while(S[i] != '<' && i < len)
                {
                    if(S[i] == ' ')                     //除掉文字前面的空格
                    {
                        while(S[i] == ' ' && i < len) i++;
                        i--;
                    }
                    if(S[i] == ' ' && (S[i+1] == '<' || !letter)) { i++; continue; } //如果文本全是空格,i++,继续
                    letter = 1;                          //否则,有字母
                    buf += S[i];                         //推进缓冲区
                    i++;
                }
                if(letter)                               //如果文本有内容
                {
                    for(j=0;j<deep;j++) printf(" ");     //再打deep个空格
                    cout<<buf;                           //输出缓冲区内容
                    puts("");
                }
                i--;
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2014-10-27 14:37  whatbeg  阅读(299)  评论(0编辑  收藏  举报