How to resolve the algorithm Eertree step by step in the Java programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Eertree step by step in the Java programming language

Table of Contents

Problem Statement

An eertree is a data structure designed for efficient processing of certain palindrome tasks, for instance counting the number of sub-palindromes in an input string. The data structure has commonalities to both tries and suffix trees.   See links below.

Construct an eertree for the string "eertree", then output all sub-palindromes by traversing the tree.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Eertree step by step in the Java programming language

This code, implements an Eertree, which is a tree-like data structure used to store palindromic substrings of a given string.

1. Class Node:

  • The Eertree is represented using a custom Node class.
  • Each node in the tree has three attributes:
    • length: The length of the palindrome represented by the node.
    • edges: A map of characters to child nodes, representing the possible extensions of the palindrome.
    • suffix: The index of the suffix node, which is the longest proper suffix of the current node's palindrome.

2. Eertree Construction (eertree method):

  • The eertree method takes a string s as input and constructs the Eertree.
  • It initializes the tree with two root nodes:
    • EVEN_ROOT: Represents palindromes of even length.
    • ODD_ROOT: Represents palindromes of odd length.
  • It iterates through the characters of the input string s.
  • For each character, it finds the longest proper suffix of the current palindrome.
  • If the suffix node has an outgoing edge for the current character, it updates the suffix node to the child node.
  • If the suffix node does not have an outgoing edge for the current character, it creates a new node in the tree and adds it as a child of the suffix node.

3. Finding Subpalindromes (subPalindromes method):

  • The subPalindromes method extracts all the subpalindromes from the Eertree.
  • It starts from the root node and recursively traverses the tree, collecting palindromes as it goes.
  • It adds palindromes to a list s, which is returned at the end.

Example:

For an input string "eertree", the Eertree will look like this:

       EVEN_ROOT
         /      \
        /        \
   e  0       r  -1
  /|\   (e)  /  \
 / | \   r  e   e
e  1   / \     \
|\| /  e   r  e  r
| | \    t   t    t
r  2    \  e      e
 |\     \     r  e
 | \      t   t   \
 e  3     e   \ e  e  0
 /|\        \  |   |
/ | \      r  e e  |
| | \    e  t  |  |   (ODD_ROOT)
| |  \  |   e  e  |
| |   \ e  |   |  |
| |    \|  e  e  |
| |     |   |   |
e  4   /|   e  e  |
|\|  / |   |   |
| | e  |   e  e  |
| |  \  \ /|  |  |
| |   \ |/ /|  |  |
r  5   \|/|/ /|  |  |
|\|   /|/|/ /|  |  |   (e)
| |  /|/|/ /| /|  |  |
| | /|/|/ /|/|/|  |  |  r
e  6  \|/|/|/| |  |  |   (e)
|\|  /|/|/|/| |  |  |
| | /|/|/|/| |  |  |  e
e  7  \|/|/|/| |  |  |  r
|\| /|/|/|/| |  |  |   (e)
| |/|/|/|/| |  |  |
e  8  \|/|/|/| |  |  |  e
|\| /|/|/|/| |  |  |   (r)
| |/|/|/|/|/| |  |  |
e  9  \|/|/|/|/|/|  |  |  e
|\| /|/|/|/|/|/|  |  |   (e)
| |/|/|/|/|/|/|/|/|  |
e 10 \|/|/|/|/|/|/|/|/|  |  (ODD_ROOT)

The subPalindromes method will extract the following palindromes from the Eertree:

e
ee
ere
erer
eertree

Source code in the java programming language

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Eertree {
    public static void main(String[] args) {
        List<Node> tree = eertree("eertree");
        List<String> result = subPalindromes(tree);
        System.out.println(result);
    }

    private static class Node {
        int length;
        Map<Character, Integer> edges = new HashMap<>();
        int suffix;

        public Node(int length) {
            this.length = length;
        }

        public Node(int length, Map<Character, Integer> edges, int suffix) {
            this.length = length;
            this.edges = edges != null ? edges : new HashMap<>();
            this.suffix = suffix;
        }
    }

    private static final int EVEN_ROOT = 0;
    private static final int ODD_ROOT = 1;

    private static List<Node> eertree(String s) {
        List<Node> tree = new ArrayList<>();
        tree.add(new Node(0, null, ODD_ROOT));
        tree.add(new Node(-1, null, ODD_ROOT));
        int suffix = ODD_ROOT;
        int n, k;
        for (int i = 0; i < s.length(); ++i) {
            char c = s.charAt(i);
            for (n = suffix; ; n = tree.get(n).suffix) {
                k = tree.get(n).length;
                int b = i - k - 1;
                if (b >= 0 && s.charAt(b) == c) {
                    break;
                }
            }
            if (tree.get(n).edges.containsKey(c)) {
                suffix = tree.get(n).edges.get(c);
                continue;
            }
            suffix = tree.size();
            tree.add(new Node(k + 2));
            tree.get(n).edges.put(c, suffix);
            if (tree.get(suffix).length == 1) {
                tree.get(suffix).suffix = 0;
                continue;
            }
            while (true) {
                n = tree.get(n).suffix;
                int b = i - tree.get(n).length - 1;
                if (b >= 0 && s.charAt(b) == c) {
                    break;
                }
            }
            tree.get(suffix).suffix = tree.get(n).edges.get(c);
        }
        return tree;
    }

    private static List<String> subPalindromes(List<Node> tree) {
        List<String> s = new ArrayList<>();
        subPalindromes_children(0, "", tree, s);
        for (Map.Entry<Character, Integer> cm : tree.get(1).edges.entrySet()) {
            String ct = String.valueOf(cm.getKey());
            s.add(ct);
            subPalindromes_children(cm.getValue(), ct, tree, s);
        }
        return s;
    }

    // nested methods are a pain, even if lambdas make that possible for Java
    private static void subPalindromes_children(final int n, final String p, final List<Node> tree, List<String> s) {
        for (Map.Entry<Character, Integer> cm : tree.get(n).edges.entrySet()) {
            Character c = cm.getKey();
            Integer m = cm.getValue();
            String pl = c + p + c;
            s.add(pl);
            subPalindromes_children(m, pl, tree, s);
        }
    }
}


  

You may also check:How to resolve the algorithm Loop over multiple arrays simultaneously step by step in the OCaml programming language
You may also check:How to resolve the algorithm Sorting algorithms/Permutation sort step by step in the Arturo programming language
You may also check:How to resolve the algorithm Cheryl's birthday step by step in the uBasic/4tH programming language
You may also check:How to resolve the algorithm Abstract type step by step in the C programming language
You may also check:How to resolve the algorithm System time step by step in the MATLAB / Octave programming language