ZOJ-1116

19 篇文章 0 订阅

XML格式校验,有点繁琐的字符串处理,稍微不小心就会错,逻辑要清晰,真实数据是必须的,不然WA了绝对DEBUG半死。。其实题目给的规则不算太多了,如果是真实XML的话会超级严格繁琐。。

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.Stack;

public class Main
{
	private static final String START = "<?xml version=\"1.0\"?>";
	private static final String END = "<?end?>";

	static Stack<Node> stack = new Stack<Node>();

	static class Node
	{
		String name;
		Node parent;
		List<Node> child = new ArrayList<Node>();
		Set<String> attr = new HashSet<String>();

		public Node(String name)
		{
			this.name = name;
		}
	}

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		String line = sc.nextLine().trim();
		while (!line.equals(START))
			line = sc.nextLine().trim();
		StringBuilder sb = new StringBuilder();
		while (true)
		{
			line = sc.nextLine().trim();
			while (!line.equals(START) && !line.equals(END))
			{
				sb.append(line);
				line = sc.nextLine().trim();
			}
			System.out.println(isWellFormed(sb) ? "well-formed"
					: "non well-formed");
			sb = new StringBuilder();
			if (line.equals(END))
				break;
		}
		sc.close();
	}

	static Node createNode(String tag)
	{
		tag = tag.trim();
		String[] ss = tag.split("\\s+");
		Node node = new Node(ss[0]);
		for (int i = 1; i < ss.length; i++)
		{
			String attr = createAttr(ss[i]);
			if (attr == null || node.attr.contains(attr))
				return null;
			node.attr.add(attr);
		}
		return node;
	}

	static String createAttr(String s)
	{
		if (s.indexOf('=') == -1)
			return null;
		String[] ss = s.split("=");
		if (ss.length != 2)
			return null;
		if (ss[1].startsWith("\"") && ss[1].endsWith("\""))
			return ss[0];
		return null;
	}

	static boolean checkParent(Node now, Node parent)
	{
		while (parent != null)
		{
			if (parent.name.equals(now.name))
				return false;
			parent = parent.parent;
		}
		return true;
	}

	static boolean isWellFormed(StringBuilder sb)
	{
		stack.clear();
		int now = 0;
		String s = sb.toString();
		boolean root = false;
		while (true)
		{
			int begin = s.indexOf('<', now);
			if (begin == -1)
				break;
			int end = s.indexOf('>', begin);
			String tag = s.substring(begin + 1, end);
			if (tag.endsWith("/"))
			{
				Node node = createNode(tag.substring(0, tag.length() - 1));
				if (node == null)
					return false;
				if (stack.isEmpty())
				{
					if (root)
						return false;
					else
						root = true;
				}
				else
				{
					Node parent = stack.peek();
					if (checkParent(node, parent))
					{
						parent.child.add(node);
						node.parent = parent;
					}
					else
						return false;
				}
			}
			else if (!tag.startsWith("/"))
			{
				Node node = createNode(tag);
				if (node == null)
					return false;
				if (stack.isEmpty() && root)
					return false;
				if (stack.isEmpty())
				{
					root = true;
					stack.push(node);
				}
				else
				{
					Node parent = stack.peek();
					if (checkParent(node, parent))
					{
						parent.child.add(node);
						node.parent = parent;
						stack.push(node);
					}
					else
						return false;
				}
			}
			else
			{
				String name = tag.substring(1).trim();
				if (stack.isEmpty() || !stack.peek().name.equals(name))
					return false;
				stack.pop();
			}
			now = end + 1;
		}
		return stack.isEmpty();
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值