Advertisement
qwerty787788

SuffixTree

Mar 20th, 2013
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.54 KB | None | 0 0
  1.  
  2. import java.io.BufferedReader;
  3. import java.io.File;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileReader;
  6. import java.io.IOException;
  7. import java.io.PrintWriter;
  8. import java.util.Arrays;
  9. import java.util.StringTokenizer;
  10.  
  11. public class SuffixTreeTask {
  12.     FastScanner in;
  13.     PrintWriter out;
  14.  
  15.     public class SuffixTree {
  16.         final int root = 0;
  17.         final int inf = Integer.MAX_VALUE / 2;
  18.         final int maxLetter = 26;
  19.  
  20.         char[] s;
  21.         boolean created;
  22.         int notHasSuflink = -1;
  23.         int n;
  24.         public int countNodes, cur, j;
  25.         int[] suflink, stringDepth, parent, start;
  26.         int[][] to;
  27.  
  28.         SuffixTree(char[] s) {
  29.             this.s = s;
  30.             n = s.length;
  31.             int maxCountNodes = 2 * n + 1;
  32.             suflink = new int[maxCountNodes];
  33.             stringDepth = new int[maxCountNodes];
  34.             parent = new int[maxCountNodes];
  35.             start = new int[maxCountNodes];
  36.             to = new int[maxCountNodes][maxLetter];
  37.  
  38.             Arrays.fill(suflink, -1);
  39.             for (int[] i : to) {
  40.                 Arrays.fill(i, -1);
  41.             }
  42.  
  43.             suflink[root] = root;
  44.             countNodes = 1;
  45.             cur = root;
  46.  
  47.             j = 0;
  48.             for (int i = 0; i < s.length; i++) {
  49.                 while (j <= i) {
  50.                     addTo(i);
  51.                     if (notHasSuflink >= 0) {
  52.                         suflink[notHasSuflink] = parent[cur];
  53.                         notHasSuflink = -1;
  54.                     }
  55.                     if (!created) {
  56.                         break;
  57.                     }
  58.  
  59.                     created = false;
  60.                     j++;
  61.                     cur = parent[cur];
  62.                     if (suflink[cur] < 0) {
  63.                         notHasSuflink = cur;
  64.                         cur = parent[cur];
  65.                     }
  66.                     cur = suflink[cur];
  67.                     while (stringDepth[cur] < i - j) {
  68.                         cur = to[cur][s[j + stringDepth[cur]] - 'a'];
  69.                     }
  70.                 }
  71.             }
  72.         }
  73.  
  74.         void addTo(int i) {
  75.             if (stringDepth[cur] < i - j) {
  76.                 new AssertionError();
  77.             }
  78.             if (stringDepth[cur] > i - j) {
  79.                 int len = i - j - stringDepth[parent[cur]];
  80.                 if (s[start[cur] + len] != s[i]) {
  81.                     int v = newNode(parent[cur], start[cur], i
  82.                             - j);
  83.                     to[v][s[start[cur] + len] - 'a'] = cur;
  84.                     start[cur] += len;
  85.                     parent[cur] = v;
  86.                     cur = v;
  87.                     created = true;
  88.                 }
  89.             }
  90.             if (stringDepth[cur] == i - j) {
  91.                 if (to[cur][s[i] - 'a'] == -1) {
  92.                     to[cur][s[i] - 'a'] = newNode(cur, i, inf);
  93.                     created = true;
  94.                 }
  95.                 cur = to[cur][s[i] - 'a'];
  96.             }
  97.         }
  98.  
  99.         int newNode(int parentOfNode, int startOfEdge, int endOfEdge) {
  100.             parent[countNodes] = parentOfNode;
  101.             start[countNodes] = startOfEdge;
  102.             stringDepth[countNodes] = endOfEdge;
  103.             to[parentOfNode][s[startOfEdge] - 'a'] = countNodes;
  104.             return countNodes++;
  105.         }
  106.  
  107.         @Override
  108.         public String toString() {
  109.             StringBuffer result = new StringBuffer();
  110.             result.append(countNodes + " " + (countNodes - 1) + "\n");
  111.             dfs(root, result);
  112.             return result.toString();
  113.         }
  114.  
  115.         void dfs(int v, StringBuffer result) {
  116.             for (int i = 0; i < 26; i++) {
  117.                 if (to[v][i] != -1) {
  118.                     int u = to[v][i];
  119.                     result.append((v + 1) + " " + (u + 1) + " "
  120.                             + (start[u] + 1) + " "
  121.                             + (stringDepth[u] == inf ? n : start[u] + stringDepth[u] - stringDepth[v])
  122.                             + "\n");
  123.                     dfs(u, result);
  124.                 }
  125.             }
  126.         }
  127.     }
  128.  
  129.     public void solve() throws IOException {
  130.         SuffixTree st = new SuffixTree(in.next().toCharArray());
  131.         out.println(st);
  132.     }
  133.  
  134.     public void run() {
  135.         try {
  136.             in = new FastScanner(new File("tree.in"));
  137.             out = new PrintWriter(new File("tree.out"));
  138.  
  139.             solve();
  140.  
  141.             out.close();
  142.         } catch (IOException e) {
  143.             e.printStackTrace();
  144.         }
  145.     }
  146.  
  147.     class FastScanner {
  148.         BufferedReader br;
  149.         StringTokenizer st;
  150.  
  151.         FastScanner(File f) {
  152.             try {
  153.                 br = new BufferedReader(new FileReader(f));
  154.             } catch (FileNotFoundException e) {
  155.                 e.printStackTrace();
  156.             }
  157.         }
  158.  
  159.         String next() {
  160.             while (st == null || !st.hasMoreTokens()) {
  161.                 try {
  162.                     st = new StringTokenizer(br.readLine());
  163.                 } catch (IOException e) {
  164.                     e.printStackTrace();
  165.                 }
  166.             }
  167.             return st.nextToken();
  168.         }
  169.  
  170.         int nextInt() {
  171.             return Integer.parseInt(next());
  172.         }
  173.  
  174.         long nextLong() {
  175.             return Long.parseLong(next());
  176.         }
  177.  
  178.         double nextDouble() {
  179.             return Double.parseDouble(next());
  180.         }
  181.  
  182.     }
  183.  
  184.     public static void main(String[] arg) {
  185.         new SuffixTreeTask().run();
  186.     }
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement