summaryrefslogtreecommitdiffstats
path: root/Algorithms/Part-II/1-WordNet/SAP.java
diff options
context:
space:
mode:
Diffstat (limited to 'Algorithms/Part-II/1-WordNet/SAP.java')
-rw-r--r--Algorithms/Part-II/1-WordNet/SAP.java232
1 files changed, 166 insertions, 66 deletions
diff --git a/Algorithms/Part-II/1-WordNet/SAP.java b/Algorithms/Part-II/1-WordNet/SAP.java
index 264102a..39c6df3 100644
--- a/Algorithms/Part-II/1-WordNet/SAP.java
+++ b/Algorithms/Part-II/1-WordNet/SAP.java
@@ -1,131 +1,231 @@
/* vim: set expandtab tabstop=4 shiftwidth=4 : */
+import java.util.Iterator;
+
public class SAP
{
- // data type use space proportional to E + V
- // all methods take time at most proportional to E + V in the worst case
- private static class SAPResult {
- private int ancestor;
- private int length;
- public SAPResult(int a, int l) {
- ancestor = a;
- length = l;
+ private final Digraph g;
+ private final BFS vBFS;
+ private final BFS wBFS;
+
+ private class BFS implements Iterable<Integer>
+ {
+ private static final int MAXINT = Integer.MAX_VALUE;
+
+ private boolean[] marked;
+ private int[] distTo;
+ private Queue<Integer> visited;
+ private Queue<Integer> q;
+
+ public BFS(int size)
+ {
+ marked = new boolean[size];
+ distTo = new int[size];
+ visited = new Queue<Integer>();
+ q = new Queue<Integer>();
+ for (int v = 0; v < size; v++) {
+ // distTo[v] = -1;
+ marked[v] = false;
+ }
+ }
+
+ public void bfs(int s)
+ {
+ clear();
+
+ marked[s] = true;
+ distTo[s] = 0;
+
+ q.enqueue(s);
+ visited.enqueue(s);
+ bfs();
}
- public int length() { return length; }
- public int ancestor() { return ancestor; }
- };
- private Digraph g;
+ public void bfs(Iterable<Integer> ss)
+ {
+ clear();
+
+ for (int s : ss) {
+ marked[s] = true;
+ distTo[s] = 0;
+ q.enqueue(s);
+ visited.enqueue(s);
+ }
+
+ bfs();
+ }
+
+ public int distTo(int v)
+ {
+ return distTo[v];
+ }
+
+ public boolean hasPathTo(int v)
+ {
+ return marked[v];
+ }
+
+ public Iterator<Integer> iterator() {
+ return visited.iterator();
+ }
+
+ public int visitedCount()
+ {
+ return visited.size();
+ }
+
+ private void clear()
+ {
+ while (!visited.isEmpty()) {
+ marked[visited.dequeue()] = false;
+ }
+ }
+
+ private void bfs()
+ {
+ while (!q.isEmpty()) {
+ int v = q.dequeue();
+ for (int w : g.adj(v)) {
+ if (!marked[w]) {
+ distTo[w] = distTo[v] + 1;
+ marked[w] = true;
+ q.enqueue(w);
+ visited.enqueue(w);
+ }
+ }
+ }
+ }
+ }
+
+ // data type use space proportional to E + V
+ // all methods take time at most proportional to E + V in the worst case
// constructor takes a digraph (not necessarily a DAG)
public SAP(Digraph G)
{
g = new Digraph(G);
+ vBFS = new BFS(G.V());
+ wBFS = new BFS(G.V());
}
// length of shortest ancestral path between v and w
// -1 if no such path
public int length(int v, int w)
{
- return ancestorAndLength(v, w).length();
+ check(v);
+ check(w);
+
+ vBFS.bfs(v);
+ wBFS.bfs(w);
+
+ return distance();
}
// a common ancestor of v and w that participates in a shortest ancestral path
// -1 if no such path
public int ancestor(int v, int w)
{
- return ancestorAndLength(v, w).ancestor();
+ check(v);
+ check(w);
+
+ vBFS.bfs(v);
+ wBFS.bfs(w);
+
+ return ancestor();
}
// length of shortest ancestral path between any vertex in v and any vertex in w
// -1 if no such path
public int length(Iterable<Integer> v, Iterable<Integer> w)
{
- return ancestorAndLength(v, w).length();
+ check(v);
+ check(w);
+
+ vBFS.bfs(v);
+ wBFS.bfs(w);
+
+ return distance();
}
// a common ancestor that participates in shortest ancestral path
// -1 if no such path
public int ancestor(Iterable<Integer> v, Iterable<Integer> w)
{
- return ancestorAndLength(v, w).ancestor();
+ check(v);
+ check(w);
+
+ vBFS.bfs(v);
+ wBFS.bfs(w);
+
+ return ancestor();
}
- private SAPResult ancestorAndLength(int v, int w)
+ private int distance()
{
- if ((Math.max(v, w) >= g.V()) || (Math.min(v, w) < 0))
- throw new IndexOutOfBoundsException("out of index");
-
- // the smallest index shall have the smallest components count
- int a, b;
- if (v < w) {
- a = v;
- b = w;
+ BFS aBFS, bBFS;
+ if (vBFS.visitedCount() < wBFS.visitedCount()) {
+ aBFS = vBFS;
+ bBFS = wBFS;
} else {
- a = w;
- b = v;
+ aBFS = wBFS;
+ bBFS = vBFS;
}
- int sol = -1;
int len = Integer.MAX_VALUE;
- if (a == b) {
- sol = a;
- len = 0;
- } else {
-
- ResizingArrayQueue<Integer> c = new ResizingArrayQueue<Integer>();
- SpecializedBFS aBFS = new SpecializedBFS(g, a, c);
- SpecializedBFS bBFS = new SpecializedBFS(g, b, null);
-
- for (int x : c) {
- if (!bBFS.hasPathTo(x)) continue;
+ for (int x : aBFS) {
+ if (bBFS.hasPathTo(x)) {
int l = aBFS.distTo(x) + bBFS.distTo(x);
- if (len > l) {
+ if (l < len) {
len = l;
- sol = x;
}
}
}
- if (sol == -1) len = -1;
-
- return new SAPResult(sol, len);
+ if (len == Integer.MAX_VALUE)
+ return -1;
+ return len;
}
- private SAPResult ancestorAndLength(Iterable<Integer> vv, Iterable<Integer> ww)
+ private int ancestor()
{
- for (int v : vv) {
- if (v < 0 || v >= g.V())
- throw new IndexOutOfBoundsException("out of index");
- }
- for (int w : ww) {
- if (w < 0 || w >= g.V())
- throw new IndexOutOfBoundsException("out of index");
+ BFS aBFS, bBFS;
+ if (vBFS.visitedCount() < wBFS.visitedCount()) {
+ aBFS = vBFS;
+ bBFS = wBFS;
+ } else {
+ aBFS = wBFS;
+ bBFS = vBFS;
}
- int sol = -1;
+ int ancestor = -1;
int len = Integer.MAX_VALUE;
- ResizingArrayQueue<Integer> c = new ResizingArrayQueue<Integer>();
- SpecializedBFS aBFS = new SpecializedBFS(g, vv, c);
- SpecializedBFS bBFS = new SpecializedBFS(g, ww, null);
-
- for (int x : c) {
- if (!bBFS.hasPathTo(x)) continue;
- int l = aBFS.distTo(x) + bBFS.distTo(x);
- if (len > l) {
- len = l;
- sol = x;
+ for (int x : aBFS) {
+ if (bBFS.hasPathTo(x)) {
+ int l = aBFS.distTo(x) + bBFS.distTo(x);
+ if (l < len) {
+ len = l;
+ ancestor = x;
+ }
}
}
- if (sol == -1) len = -1;
+ return ancestor;
+ }
- SAPResult res = new SAPResult(sol, len);
+ private void check(int v)
+ {
+ if (v < 0 || v >= g.V())
+ throw new IndexOutOfBoundsException("out of index");
+ }
- return res;
+ private void check(Iterable<Integer> vs)
+ {
+ for (int v : vs) {
+ check(v);
+ }
}
// for unit testing of this class (such as the one below)