Advertisement
Guest User

ST.java

a guest
Dec 5th, 2012
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.44 KB | None | 0 0
  1. import java.io.*;
  2. import java.util.*;
  3.  
  4. public class ST {
  5.  
  6.     class SuffixTree {
  7.         final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
  8.         final int oo = Integer.MAX_VALUE/2;
  9.         Node [] nodes;
  10.         int length = -1, currentNode = -1, needSuffixLink = -1, remainder = 0;
  11.         final int root = 1;
  12.         int active_node = root, active_length = 0;
  13.         int active_edge = 0;
  14.         char [] text;
  15.  
  16.         class Node {
  17.             int start = -1, end = oo, parentDepth, link = -1;
  18.             TreeMap<Character, Integer> next;
  19.             public Node() {
  20.                 next = new TreeMap<Character, Integer>();
  21.             }
  22.  
  23.             public Node(int start) {
  24.                 this();
  25.                 this.start = start;
  26.             }
  27.  
  28.             public Node(int start, int end) {
  29.                 this();
  30.                 this.start = start;
  31.                 this.end = end;
  32.             }
  33.  
  34.             public int edgeLength() {
  35.                 return Math.min(end, length + 1) - start;
  36.             }
  37.         }
  38.  
  39.         public SuffixTree(int length) {
  40.             nodes = new Node[2*length + 2];
  41.             text = new char[length];
  42.             nodes[++currentNode] = new Node();
  43.             nodes[++currentNode] = new Node();
  44.             for (int i = 0; i < ALPHABET.length(); i++)
  45.                 nodes[0].next.put(ALPHABET.charAt(i), 1);
  46.             nodes[1].link = 0;
  47.         }
  48.  
  49.  
  50.  
  51.         private void addSuffixLink(int node) {
  52.             if (needSuffixLink > 0)
  53.                 nodes[needSuffixLink].link = node;
  54.             needSuffixLink = node;
  55.         }
  56.  
  57.         char active_edge() {
  58.             return active_edge < 0 ? '\0' : text[active_edge];
  59.         }
  60.  
  61.         int step = 1;
  62.  
  63.         public void addChar(char c) throws Exception {
  64.  
  65.             needSuffixLink = -1;
  66.             text[++length] = c;
  67.             remainder++;
  68.             cut:while(remainder > 0) {
  69.                 if (active_length == 0) active_edge = length;
  70.  
  71.  
  72.                 if (nodes[active_node].next.containsKey(active_edge())) {
  73.                     int next = nodes[active_node].next.get(active_edge());
  74.  
  75.                     if (active_length >= nodes[next].edgeLength()) { //if the edge we came to is shorter than active_length - go down
  76.                         active_edge += nodes[next].edgeLength();
  77.                         active_length -= nodes[next].edgeLength();
  78.                         active_node = next;
  79.                         continue cut;
  80.                     }
  81.  
  82.  
  83.                     if (text[nodes[next].start + active_length] == c) {  //character c is on the edge
  84.                         active_length++;
  85.                         if (active_length == nodes[next].edgeLength()) {
  86.                             active_node = next;
  87.                             active_edge = -1;
  88.                             active_length = 0;
  89.                         }
  90.                         break;
  91.                     }
  92.                 }
  93.                 if (!nodes[active_node].next.containsKey(active_edge())) {   //adding new node right to the active_node
  94.                     nodes[++currentNode] = new Node(length);
  95.                     nodes[active_node].next.put(active_edge(), currentNode);
  96.                     remainder--;
  97.                 } else {
  98.                     int next = nodes[active_node].next.get(active_edge());   //here we must split the edge
  99.  
  100.                     if (active_length >= nodes[next].edgeLength()) {
  101.                         active_edge += nodes[next].edgeLength();
  102.                         active_length -= nodes[next].edgeLength();
  103.                         active_node = next;
  104.                         continue cut;
  105.                     }
  106.  
  107.                     nodes[++currentNode] = new Node(nodes[next].start, nodes[next].start + active_length); //split Node
  108.                     nodes[active_node].next.put(active_edge(), currentNode);
  109.                     nodes[++currentNode] = new Node(length); //node with single character on edge
  110.                     nodes[currentNode - 1].next.put(c, currentNode);
  111.                     nodes[next].start += active_length;
  112.                     nodes[currentNode - 1].next.put(text[nodes[next].start], next);
  113.                     addSuffixLink(currentNode - 1);
  114.                     remainder--;
  115.                 }
  116.  
  117.                 if (active_node == root && active_length > 0) { //after insertion, if we're at the root - set active_edge to next_suffix_to_add[0]
  118.                     active_length--;
  119.                     active_edge = length - remainder + 1;
  120.                 } else {
  121.                     active_node = nodes[active_node].link > 0 ? nodes[active_node].link : root; //otherwise - follow the suffix link (or go to root)
  122.                 }
  123.             }
  124.         }
  125.  
  126.         int countDistinctSubstrings(int x) {
  127.             int res = 0;
  128.             if (x != root)
  129.                 res += nodes[x].edgeLength();
  130.             for (int node : nodes[x].next.values())
  131.                 res += countDistinctSubstrings(node);
  132.             return res;
  133.         }
  134.     }
  135.  
  136.  
  137.     public ST() throws Exception {
  138.         BufferedReader in1, in2;
  139.         SuffixTree st = new SuffixTree(8);
  140.         String line = "aabaaabb";
  141.         for (int i = 0; i < line.length(); i++)
  142.             st.addChar(line.charAt(i));
  143.  
  144.         System.out.println(st.countDistinctSubstrings(st.root));
  145.     }
  146.  
  147.     public static void main(String ... args) throws Exception{
  148.         new ST();
  149.     }
  150. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement