---
# System prepended metadata

title: Untitled

---

```java

import java.util.*;

public class ParseHtml {
    /*
    *
input aa<a>bbb<b>ccc</b>gg</a>zzz
output :
1. aa
2. a: bbb
3. a+b: ccc
4. a: gg
5. zzz
    * */
    public static void main(String[] args){
        ParseHtml parseHtml = new ParseHtml();
        String input = "aa<a>bbb<b>ccc</b>gg</a>zzz";
        try {
            List<HtmlText> list = parseHtml.parseSeq(input);
            for (int i = 0; i < list.size(); i++) {
                HtmlText text = list.get(i);
                System.out.println(text.content + " " + text.tags);
            }
        } catch (Throwable t) {
            System.out.println(t);
        }
    }

    public List<HtmlText> parseSeq(String input) throws Exception {
        StringBuilder value = new StringBuilder();
        ArrayList<String> tags = new ArrayList<>();
        ArrayList<HtmlText> ans = new ArrayList<>();
        Stack<String> sk = new Stack<>();
        int idx = 0, N = input.length();
        while (idx < N) {
            char cur = input.charAt(idx);
            if (cur == '<') {
                if (value.length() > 0) {
                    ans.add(new HtmlText(value.toString(), new HashSet<String>(tags)));
                }
                value = new StringBuilder();
                Pair<String, Integer> pair = getTag(input, idx);
                if (isOppositeTag(pair.a)) {
                    if (sk.isEmpty()) throw new Exception("syntax error: only / tag " + pair.a);
                    String tag = sk.pop();
                    if (!isMatchOppositeTag(tag, pair.a)) {
                        throw new Exception("syntax error: " + pair.a + " not match any tag");
                    } else {
                        tags.remove(tags.size() - 1);
                    }
                } else {
                    tags.add(pair.a);
                    sk.add(pair.a);
                }
                idx = pair.b + 1;
            } else {
                value.append(cur);
                idx++;
            }
        }
        if (!tags.isEmpty()) {
            throw new Exception("syntax error: " + tags + " not match any tag");
        }
        if (value.length() > 0) {
            ans.add(new HtmlText(value.toString(), new HashSet<>()));
        }
        return ans;
    }

    private boolean isOppositeTag(String a) {
        return a.contains("/");
    }
    private boolean isMatchOppositeTag(String a, String b) {
        int aIdx = 0, bIdx = 0;
        while (aIdx < a.length() && bIdx < b.length()) {
            char aChar = a.charAt(aIdx);
            char bChar = b.charAt(bIdx);
            if (aChar == '/') {
                aIdx++;
            } else if (bChar == '/') {
                bIdx++;
            } else if (aChar != bChar) {
                return false;
            } else {
                aIdx++;
                bIdx++;
            }
        }
        return aIdx == a.length() && bIdx == b.length();
    }

    private Pair<String, Integer> getTag(String input, Integer curIdx) throws Exception {
        if (input.charAt(curIdx) != '<') throw new Exception("tag doesn't start from <");
        curIdx++;
        String ans = "";
        while (input.charAt(curIdx) != '>') {
            ans += input.charAt(curIdx++);
        }
        return new Pair(ans, curIdx);
    }
}

class Pair<A, B> {
    A a;
    B b;
    Pair(A a, B b) {
        this.a = a;
        this.b = b;
    }
}

class HtmlText {
    String content;
    Set<String> tags;
    HtmlText(String a, Set<String> b) {
        this.content = a;
        this.tags = b;
    }
}

```
output
```
aa []
bbb [a]
ccc [a, b]
gg [a]
zzz []
```






```java=
    public static void main(String[] args) {
        TestQ tt = new TestQ();
        tt.test2(5, 2, 4);
        System.out.println("======");
        tt.test2(5, 2, 3);
    }

    public void test2(int N, int X, int Y) {
        Graph graph = new Graph();
        for (int i = 1; i <= N; i++) {
            Node node = new Node(i);
            graph.map.put(i, node);
        }
        int tmp = Y, tmp1 = X;
        Y = Math.max(tmp, tmp1);
        X = Math.min(tmp, tmp1);
        Node node1 = graph.map.get(X);
        Node node2 = graph.map.get(Y);
        Edge edge;
        edge = new Edge(node1, node2, 1);
        node1.edges.add(edge);
        graph.edges.add(edge);

        for (int k : graph.map.keySet()) {
            Node node = graph.map.get(k);
            Node nextNode = graph.map.get(node.value + 1);
            if (nextNode == null) continue;
            if (nextNode.value == Y && node.value == X) continue;
            Edge ee = new Edge(node, nextNode, 1);
            node.edges.add(ee);
            graph.edges.add(ee);
        }
        int ans = 0;
        for (int i = 0; i < graph.edges.size(); i++) {
            if (graph.edges.get(i).cost == 1) {
                ans++;
            }
        }
        System.out.println("1 : " + ans);
        for (int dis = 2; dis < N; dis++) {
            int tmpAns = 0;
            for (Integer k : graph.map.keySet()) {
                Node node = graph.map.get(k);
                tmpAns += traverse(node, dis, X, Y);
            }
            System.out.println(dis + " : " + tmpAns);
        }
    }

    public int traverse(Node curNode, int dis, int X, int Y) {
        if (dis == 0) {
            return 1;
        }
        if (curNode.value == X && curNode.value + dis >= Y) {
            //fast
            List<Edge> edges = curNode.edges;
            Node nextNode = null;
            for (int fi = 0; fi < edges.size(); fi++) {
                if (nextNode == null) {
                    nextNode = edges.get(fi).e;
                } else if (nextNode.value < edges.get(fi).e.value) {
                    nextNode = edges.get(fi).e;
                }
            }
            if (nextNode == null) {
                return 0;
            }
            return traverse(nextNode, dis - 1, X, Y);
        } else {
            // slow
            List<Edge> edges = curNode.edges;
            int tmp = 0;
            for (int fi = 0; fi < edges.size(); fi++) {
                Node nextNode = edges.get(fi).e;
                tmp += traverse(nextNode, dis - 1, X, Y);
            }
            return tmp;
        }
    }


public class Edge {
    Node s;
    Node e;
    int cost = 0;

    Edge(Node s, Node e, int cost) {
        this.s = s;
        this.e = e;
        this.cost = cost;
    }

}
public class Node {
    int value = -1;
    List<Edge> edges = new ArrayList<>();
    public Node(int value) {
        this.value = value;
    }

}

public class Graph {
    Map<Integer, Node> map = new LinkedHashMap<>(); //1:node, 2: node
    List<Edge> edges = new ArrayList<>();// 1-2, 2-3
}


```

output 
```
1 : 5
2 : 4
3 : 1
4 : 0
======
1 : 4
2 : 3
3 : 2
4 : 1
```