Java Dizgi Eşleme Algoritmaları
Apostolico-Crochemore algoritması
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
import java.util.ArrayList; import java.util.List; public class AC { private static void preKmp(char[] x, int[] kmpNext) { int i, j, m = (x.length - 1); i = 0; j = kmpNext[0] = -1; while (i < m) { while (j > -1 && x[i] != x[j]) j = kmpNext[j]; i++; j++; if (x[i] == x[j]) kmpNext[i] = kmpNext[j]; else kmpNext[i] = j; } } public static List<Integer> findAll(String pattern, String source) { char[] ptrn = pattern.toCharArray(), y = source.toCharArray(); char[] x = new char[ptrn.length + 1]; System.arraycopy(ptrn, 0, x, 0, ptrn.length); int i, j, k, ell, m = ptrn.length, n = y.length; List<Integer> result = new ArrayList<Integer>(); int[] kmpNext = new int[x.length]; /* Preprocessing */ preKmp(x, kmpNext); for (ell = 1; x[ell - 1] == x[ell]; ell++) ; if (ell == m) ell = 0; /* Searching */ i = ell; j = k = 0; while (j <= n - m) { while (i < m && x[i] == y[i + j]) ++i; if (i >= m) { while (k < ell && x[k] == y[j + k]) ++k; if (k >= ell) result.add(j); } j += (i - kmpNext[i]); if (i == ell) k = Math.max(0, k - 1); else if (kmpNext[i] <= ell) { k = Math.max(0, kmpNext[i]); i = ell; } else { k = ell; i = kmpNext[i]; } } return result; } public static AC compile(String pattern) { char[] ptrn = pattern.toCharArray(); char[] x = new char[ptrn.length + 1]; System.arraycopy(ptrn, 0, x, 0, ptrn.length); int ell, m = ptrn.length; int[] kmpNext = new int[x.length]; preKmp(x, kmpNext); for (ell = 1; x[ell - 1] == x[ell]; ell++) ; if (ell == m) ell = 0; AC ac = new AC(); ac.m = m; ac.ell = ell; ac.x = x; ac.kmpNext = kmpNext; return ac; } public List<Integer> findAll(String source) { char[] y = source.toCharArray(); int i, j, k, n = y.length; List<Integer> result = new ArrayList<Integer>(); i = ell; j = k = 0; while (j <= n - m) { while (i < m && x[i] == y[i + j]) ++i; if (i >= m) { while (k < ell && x[k] == y[j + k]) ++k; if (k >= ell) result.add(j); } j += (i - kmpNext[i]); if (i == ell) k = Math.max(0, k - 1); else if (kmpNext[i] <= ell) { k = Math.max(0, kmpNext[i]); i = ell; } else { k = ell; i = kmpNext[i]; } } return result; } private int m, ell; private char[] x; private int[] kmpNext; } |
Apostolico-Giancarlo algoritması
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
import java.util.ArrayList; import java.util.List; public class AG { private static void preBmBc(char[] x, int bmBc[]) { int i, m = x.length; for (i = 0; i < bmBc.length; ++i) bmBc[i] = m; for (i = 0; i < m - 1; ++i) bmBc[x[i]] = m - i - 1; } private static void suffixes(char[] x, int[] suff) { int f = 0, g, i, m = x.length; suff[m - 1] = m; g = m - 1; for (i = m - 2; i >= 0; --i) { if (i > g && suff[i + m - 1 - f] < i - g) suff[i] = suff[i + m - 1 - f]; else { if (i < g) g = i; f = i; while (g >= 0 && x[g] == x[g + m - 1 - f]) --g; suff[i] = f - g; } } } private static void preBmGs(char[] x, int bmGs[], int[] suff) { int i, j, m = x.length; suffixes(x, suff); for (i = 0; i < m; ++i) bmGs[i] = m; j = 0; for (i = m - 1; i >= 0; --i) if (suff[i] == i + 1) for (; j < m - 1 - i; ++j) if (bmGs[j] == m) bmGs[j] = m - 1 - i; for (i = 0; i <= m - 2; ++i) bmGs[m - 1 - suff[i]] = m - 1 - i; } private static void arrayCpy(int[] trg, int trgIdx, int[] src, int srcIdx, int length) { for (int i = 0; i < length; i++) trg[trgIdx + i] = src[srcIdx + i]; } public static List<Integer> findAll(String pattern, String source) { char[] x = pattern.toCharArray(), y = source.toCharArray(); int i, j, k, s, shift, m = x.length, n = y.length; List<Integer> result = new ArrayList<Integer>(); int[] bmGs = new int[m]; int[] skip = new int[m]; int[] suff = new int[m]; int[] bmBc = new int[65536]; /* Preprocessing */ preBmGs(x, bmGs, suff); preBmBc(x, bmBc); for (i = 0; i < m; i++) skip[i] = 0; /* Searching */ j = 0; while (j <= n - m) { i = m - 1; while (i >= 0) { k = skip[i]; s = suff[i]; if (k > 0) if (k > s) { if (i + 1 == s) i = (-1); else i -= s; break; } else { i -= k; if (k < s) break; } else { if (x[i] == y[i + j]) --i; else break; } } if (i < 0) { result.add(j); skip[m - 1] = m; shift = bmGs[0]; } else { skip[m - 1] = m - 1 - i; shift = Math.max(bmGs[i], bmBc[y[i + j]] - m + 1 + i); } j += shift; arrayCpy(skip, 0, skip, shift, (m - shift)); for (i = 0; i < shift; i++) skip[m - shift + i] = 0; } return result; } public static AG compile(String pattern) { char[] x = pattern.toCharArray(); int i, m = x.length; int[] bmGs = new int[m]; int[] skip = new int[m]; int[] suff = new int[m]; int[] bmBc = new int[65536]; preBmGs(x, bmGs, suff); preBmBc(x, bmBc); for (i = 0; i < m; i++) skip[i] = 0; AG ag = new AG(); ag.bmGs = bmGs; ag.skip = skip; ag.suff = suff; ag.bmBc = bmBc; ag.x = x; ag.m = m; return ag; } public List<Integer> findAll(String source) { char[] y = source.toCharArray(); int i, j, k, s, shift, n = y.length; List<Integer> result = new ArrayList<Integer>(); j = 0; while (j <= n - m) { i = m - 1; while (i >= 0) { k = skip[i]; s = suff[i]; if (k > 0) if (k > s) { if (i + 1 == s) i = (-1); else i -= s; break; } else { i -= k; if (k < s) break; } else { if (x[i] == y[i + j]) --i; else break; } } if (i < 0) { result.add(j); skip[m - 1] = m; shift = bmGs[0]; } else { skip[m - 1] = m - 1 - i; shift = Math.max(bmGs[i], bmBc[y[i + j]] - m + 1 + i); } j += shift; arrayCpy(skip, 0, skip, shift, (m - shift)); for (i = 0; i < shift; i++) skip[m - shift + i] = 0; } return result; } private int[] bmGs, skip, suff, bmBc; private char[] x; private int m; } |
Brute Force algoritması
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import java.util.ArrayList; import java.util.List; public class BF { public static List<Integer> findAll(String pattern, String source) { char[] x = pattern.toCharArray(), y = source.toCharArray(); int i, j, m = x.length, n = y.length; List<Integer> result = new ArrayList<Integer>(); /* Searching */ for (j = 0; j <= n - m; ++j) { for (i = 0; i < m && x[i] == y[i + j]; ++i) ; if (i >= m) result.add(j); } return result; } } |
Boyer-Moore algorithması
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
import java.util.ArrayList; import java.util.List; public class BM { private static void preBmBc(char[] x, int bmBc[]) { int i, m = x.length; for (i = 0; i < bmBc.length; ++i) bmBc[i] = m; for (i = 0; i < m - 1; ++i) bmBc[x[i]] = m - i - 1; } private static void suffixes(char[] x, int[] suff) { int f = 0, g, i, m = x.length; suff[m - 1] = m; g = m - 1; for (i = m - 2; i >= 0; --i) { if (i > g && suff[i + m - 1 - f] < i - g) suff[i] = suff[i + m - 1 - f]; else { if (i < g) g = i; f = i; while (g >= 0 && x[g] == x[g + m - 1 - f]) --g; suff[i] = f - g; } } } private static void preBmGs(char[] x, int bmGs[]) { int i, j, m = x.length; int[] suff = new int[m]; suffixes(x, suff); for (i = 0; i < m; ++i) bmGs[i] = m; j = 0; for (i = m - 1; i >= 0; --i) if (suff[i] == i + 1) for (; j < m - 1 - i; ++j) if (bmGs[j] == m) bmGs[j] = m - 1 - i; for (i = 0; i <= m - 2; ++i) bmGs[m - 1 - suff[i]] = m - 1 - i; } public static List<Integer> findAll(String pattern, String source) { char[] x = pattern.toCharArray(), y = source.toCharArray(); int i, j, m = x.length, n = y.length; List<Integer> result = new ArrayList<Integer>(); int[] bmGs = new int[m]; int[] bmBc = new int[65536]; /* Preprocessing */ preBmGs(x, bmGs); preBmBc(x, bmBc); /* Searching */ j = 0; while (j <= n - m) { for (i = m - 1; i >= 0 && x[i] == y[i + j]; --i) ; if (i < 0) { result.add(j); j += bmGs[0]; } else j += Math.max(bmGs[i], bmBc[y[i + j]] - m + 1 + i); } return result; } public static BM compile(String pattern) { char[] x = pattern.toCharArray(); int m = x.length; int[] bmGs = new int[m]; int[] bmBc = new int[65536]; preBmGs(x, bmGs); preBmBc(x, bmBc); BM bm = new BM(); bm.bmBc = bmBc; bm.bmGs = bmGs; bm.x = x; bm.m = m; return bm; } public List<Integer> findAll(String source) { char[] y = source.toCharArray(); int i, j, n = y.length; List<Integer> result = new ArrayList<Integer>(); j = 0; while (j <= n - m) { for (i = m - 1; i >= 0 && x[i] == y[i + j]; --i) ; if (i < 0) { result.add(j); j += bmGs[0]; } else j += Math.max(bmGs[i], bmBc[y[i + j]] - m + 1 + i); } return result; } private int[] bmGs, bmBc; private char[] x; private int m; } |
Backward Nondeterministic Dawg Matching algoritması
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
import java.util.ArrayList; import java.util.List; public class BNDM { public static List<Integer> findAll(String pattern, String source) { char[] x = pattern.toCharArray(), y = source.toCharArray(); int i, j, s, d, last, m = x.length, n = y.length; List<Integer> result = new ArrayList<Integer>(); int[] b = new int[65536]; /* Pre processing */ for (i = 0; i < b.length; i++) b[i] = 0; s = 1; for (i = m - 1; i >= 0; i--) { b[x[i]] |= s; s <<= 1; } /* Searching phase */ j = 0; while (j <= n - m) { i = m - 1; last = m; d = ~0; while (i >= 0 && d != 0) { d &= b[y[j + i]]; i--; if (d != 0) { if (i >= 0) last = i + 1; else result.add(j); } d <<= 1; } j += last; } return result; } public static BNDM compile(String pattern) { char[] x = pattern.toCharArray(); int i, s, m = x.length; int[] b = new int[65536]; for (i = 0; i < b.length; i++) b[i] = 0; s = 1; for (i = m - 1; i >= 0; i--) { b[x[i]] |= s; s <<= 1; } BNDM bndm = new BNDM(); bndm.m = m; bndm.b = b; return bndm; } public List<Integer> findAll(String source) { char[] y = source.toCharArray(); int i, j, d, last, n = y.length; List<Integer> result = new ArrayList<Integer>(); j = 0; while (j <= n - m) { i = m - 1; last = m; d = ~0; while (i >= 0 && d != 0) { d &= b[y[j + i]]; i--; if (d != 0) { if (i >= 0) last = i + 1; else result.add(j); } d <<= 1; } j += last; } return result; } private int[] b; private int m; } |
Backward Oracle Matching algoritması
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.ArrayList; import java.util.List; public class BOM { private static final char TRUE = 1; private static final char FALSE = 0; private static final int UNDEFINED = -1; private static int getTransition(char[] x, int p, Cell[] list, char c) { Cell cell; if (p > 0 && x[p - 1] == c) return (p - 1); else { cell = list[p]; while (cell != null) if (x |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
[cell.element] == c) return (cell.element); else cell = cell.next; return (UNDEFINED); } } private static void setTransition(int p, int q, Cell[] list) { Cell cell = new Cell(); cell.element = q; cell.next = list[p]; list[p] = cell; } private static void oracle(char[] x, char[] t, Cell[] list) { int i, p, q = UNDEFINED, m = x.length - 1; int[] s = new int[x.length]; char c; s[m] = m + 1; for (i = m; i > 0; --i) { c = x[i - 1]; p = s[i]; while (p <= m && (q = getTransition(x, p, list, c)) == UNDEFINED) { setTransition(p, i - 1, list); p = s[p]; } s[i - 1] = (p == m + 1 ? m : q); } p = 0; while (p <= m) { t[p] = TRUE; p = s[p]; } } public static List findAll(String pattern, String source) { char[] ptrn = pattern.toCharArray(), y = source.toCharArray(); char[] x = new char[ptrn.length + 1]; System.arraycopy(ptrn, 0, x, 0, ptrn.length); int i, j, p, period = 0, q, shift, m = ptrn.length, n = y.length; List result = new ArrayList(); char[] t = new char[x.length]; Cell[] list = new Cell[x.length]; /* Preprocessing */ for (i = 0; i < t.length; i++) t[i] = FALSE; oracle(x, t, list); /* Searching */ j = 0; while (j = 0 && (q = getTransition(x, p, list, y[i + j])) != UNDEFINED) { p = q; if (t[p] == TRUE) { period = shift; shift = i; } --i; } if (i < 0) { result.add(j); shift = period; } j += shift; } return result; } public static BOM compile(String pattern) { char[] ptrn = pattern.toCharArray(); char[] x = new char[ptrn.length + 1]; System.arraycopy(ptrn, 0, x, 0, ptrn.length); int i, m = ptrn.length; char[] t = new char[x.length]; Cell[] list = new Cell[x.length]; for (i = 0; i < t.length; i++) t[i] = FALSE; oracle(x, t, list); BOM bom = new BOM(); bom.m = m; bom.x = x; bom.t = t; bom.list = list; return bom; } public List findAll(String source) { char[] y = source.toCharArray(); int i, j, p, period = 0, q, shift, n = y.length; List result = new ArrayList(); j = 0; while (j = 0 && (q = getTransition(x, p, list, y[i + j])) != UNDEFINED) { p = q; if (t[p] == TRUE) { period = shift; shift = i; } --i; } if (i < 0) { result.add(j); shift = period; } j += shift; } return result; } private char[] x, t; private Cell[] list; private int m; private static class Cell { int element; Cell next; } } |
Berry-Ravindran algoritması
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
import java.util.ArrayList; import java.util.List; public class BR { private static void preBrBc(char[] x, int[][] brBc) { int a, b, i, m = x.length; for (a = 0; a < brBc.length; ++a) for (b = 0; b < brBc.length; ++b) brBc[a][b] = m + 2; for (a = 0; a < brBc.length; ++a) brBc[a][x[0]] = m + 1; for (i = 0; i < m - 1; ++i) brBc[x[i]][x[i + 1]] = m - i; for (a = 0; a < brBc.length; ++a) brBc[x[m - 1]][a] = 1; } private static int arrayCmp(char[] a, int aIdx, char[] b, int bIdx, int length) { int i = 0; for (i = 0; i < length && aIdx + i < a.length && bIdx + i < b.length; i++) { if (a[aIdx + i] == b[bIdx + i]) ; else if (a[aIdx + i] > b[bIdx + i]) return 1; else return 2; } if (i < length) if (a.length - aIdx == b.length - bIdx) return 0; else if (a.length - aIdx > b.length - bIdx) return 1; else return 2; else return 0; } private static int calculateBrBcSize(char[] x, char[] y) { int i; char maxChar = 0; for (i = 0; i < x.length; i++) if (x[i] > maxChar) maxChar = x[i]; for (i = 0; i < y.length; i++) if (y[i] > maxChar) maxChar = y[i]; maxChar++; return maxChar; } public static List<Integer> findAll(String pattern, String source) { char[] x = pattern.toCharArray(), src = source.toCharArray(); char[] y = new char[src.length + 2]; System.arraycopy(src, 0, y, 0, src.length); int j, m = x.length, n = src.length; List<Integer> result = new ArrayList<Integer>(); if(calculateBrBcSize(x, src) > 256) return null; int[][] brBc = new int[256][256]; /* Preprocessing */ preBrBc(x, brBc); /* Searching */ j = 0; y[n + 1] = '\0'; while (j < n - m) { if (arrayCmp(x, 0, y, j, m) == 0) result.add(j); j += brBc[y[j + m]][y[j + m + 1]]; } if(j == n - m && arrayCmp(x, 0, y, j, m) == 0) result.add(j); return result; } public static BR compile(String pattern) { char[] x = pattern.toCharArray(); int m = x.length; int[][] brBc = new int[256][256]; preBrBc(x, brBc); BR br = new BR(); br.brBc = brBc; br.m = m; br.x = x; return br; } public List<Integer> findAll(String source) { char[] src = source.toCharArray(); char[] y = new char[src.length + 2]; System.arraycopy(src, 0, y, 0, src.length); int j, n = src.length; List<Integer> result = new ArrayList<Integer>(); if(calculateBrBcSize(x, src) > 256) return null; j = 0; y[n + 1] = '\0'; while (j < n - m) { if (arrayCmp(x, 0, y, j, m) == 0) result.add(j); j += brBc[y[j + m]][y[j + m + 1]]; } if(j == n - m && arrayCmp(x, 0, y, j, m) == 0) result.add(j); return result; } private char[] x; private int m; private int[][] brBc; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
import java.util.ArrayList; import java.util.List; public class CLS { private static int preColussi(char[] x, int[] h, int[] next, int[] shift) { int i, k, nd, q, r = 0, s, m = (x.length - 1); int[] hmax = new int[x.length]; int[] kmin = new int[x.length]; int[] nhd0 = new int[x.length]; int[] rmin = new int[x.length]; /* Computation of hmax */ i = k = 1; do { while (x[i] == x[i - k]) i++; hmax[k] = i; q = k + 1; while (hmax[q - k] + k < i) { hmax[q] = hmax[q - k] + k; q++; } k = q; if (k == i + 1) i = k; } while (k <= m); /* Computation of kmin */ for (i = 0; i < m; i++) kmin[i] = 0; for (i = m; i >= 1; --i) if (hmax[i] < m) kmin[hmax[i]] = i; /* Computation of rmin */ for (i = m - 1; i >= 0; --i) { if (hmax[i + 1] == m) r = i + 1; if (kmin[i] == 0) rmin[i] = r; else rmin[i] = 0; } /* Computation of h */ s = -1; r = m; for (i = 0; i < m; ++i) if (kmin[i] == 0) h[--r] = i; else h[++s] = i; nd = s; /* Computation of shift */ for (i = 0; i <= nd; ++i) shift[i] = kmin[h[i]]; for (i = nd + 1; i < m; ++i) shift[i] = rmin[h[i]]; shift[m] = rmin[0]; /* Computation of nhd0 */ s = 0; for (i = 0; i < m; ++i) { nhd0[i] = s; if (kmin[i] > 0) ++s; } /* Computation of next */ for (i = 0; i <= nd; ++i) next[i] = nhd0[h[i] - kmin[h[i]]]; for (i = nd + 1; i < m; ++i) next[i] = nhd0[m - rmin[h[i]]]; next[m] = nhd0[m - rmin[h[m - 1]]]; return (nd); } public static List<Integer> findAll(String pattern, String source) { char[] ptrn = pattern.toCharArray(), y = source.toCharArray(); char[] x = new char[ptrn.length + 1]; System.arraycopy(ptrn, 0, x, 0, ptrn.length); int i, j, last, nd, m = ptrn.length, n = y.length; List<Integer> result = new ArrayList<Integer>(); int[] h = new int[x.length]; int[] next = new int[x.length]; int[] shift = new int[x.length]; /* Processing */ nd = preColussi(x, h, next, shift); /* Searching */ i = j = 0; last = -1; while (j <= n - m) { while (i < m && last < j + h[i] && x[h[i]] == y[j + h[i]]) i++; if (i >= m || last >= j + h[i]) { result.add(j); i = m; } if (i > nd) last = j + m - 1; j += shift[i]; i = next[i]; } return result; } public static CLS compile(String pattern) { char[] ptrn = pattern.toCharArray(); char[] x = new char[ptrn.length + 1]; System.arraycopy(ptrn, 0, x, 0, ptrn.length); int nd, m = ptrn.length; int[] h = new int[x.length]; int[] next = new int[x.length]; int[] shift = new int[x.length]; /* Processing */ nd = preColussi(x, h, next, shift); CLS cls = new CLS(); cls.x = x; cls.h = h; cls.m = m; cls.next = next; cls.shift = shift; cls.nd = nd; return cls; } public List<Integer> findAll(String source) { char[] y = source.toCharArray(); int i, j, last, n = y.length; List<Integer> result = new ArrayList<Integer>(); i = j = 0; last = -1; while (j <= n - m) { while (i < m && last < j + h[i] && x[h[i]] == y[j + h[i]]) i++; if (i >= m || last >= j + h[i]) { result.add(j); i = m; } if (i > nd) last = j + m - 1; j += shift[i]; i = next[i]; } return result; } private char[] x; private int[] h, next, shift; private int nd, m; } |
Deterministic Finite Automaton algoritması
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
import java.util.ArrayList; import java.util.List; public class DFA { private static void preAut(char[] x, Graph aut) { int i, state, target, oldTarget, m = x.length; for (state = Automata.getInitial(aut), i = 0; i < m; ++i) { oldTarget = Automata.getTarget(aut, state, x[i]); target = Automata.newVertex(aut); Automata.setTarget(aut, state, x[i], target); Automata.copyVertex(aut, target, oldTarget); state = target; } Automata.setTerminal(aut, state); } public static List<Integer> findAll(String pattern, String source) { char[] x = pattern.toCharArray(), y = source.toCharArray(); int j, state, m = x.length, n = y.length; List<Integer> result = new ArrayList<Integer>(); Graph aut; /* Preprocessing */ aut = Automata.newAutomaton(m + 1, (m + 1) * 65536); preAut(x, aut); /* Searching */ for (state = Automata.getInitial(aut), j = 0; j < n; ++j) { state = Automata.getTarget(aut, state, y[j]); if (Automata.isTerminal(aut, state)) result.add(j - m + 1); } return result; } public static DFA compile(String pattern) { char[] x = pattern.toCharArray(); int m = x.length; Graph aut; aut = Automata.newAutomaton(m + 1, (m + 1) * 65536); preAut(x, aut); DFA dfa = new DFA(); dfa.aut = aut; dfa.m = m; return dfa; } public List<Integer> findAll(String source) { char[] y = source.toCharArray(); int j, state, n = y.length; List<Integer> result = new ArrayList<Integer>(); for (state = Automata.getInitial(aut), j = 0; j < n; ++j) { state = Automata.getTarget(aut, state, y[j]); if (Automata.isTerminal(aut, state)) result.add(j - m + 1); } return result; } private Graph aut; private int m; private static class Graph { private int vertexNumber, edgeNumber, vertexCounter, initial; private int[] terminal, target, suffixLink, length, position, shift; } private static class Automata { private static final int UNDEFINED = -1; /* * returns a new data structure for a graph with v vertices and e edges */ public static Graph newGraph(int v, int e) { Graph g = new Graph(); g.vertexNumber = v; g.edgeNumber = e; g.initial = 0; g.vertexCounter = 1; return (g); } /* * returns a new data structure for a automaton with v vertices and e * edges */ public static Graph newAutomaton(int v, int e) { Graph aut; aut = newGraph(v, e); aut.target = new int[e]; ; aut.terminal = new int[v]; return (aut); } /* * returns a new data structure for a suffix automaton with v vertices * and e edges */ public static Graph newSuffixAutomaton(int v, int e) { Graph aut; aut = newAutomaton(v, e); aut.target = new int[e]; for (int i = 0; i < e; i++) aut.target[i] = UNDEFINED; aut.suffixLink = new int[v]; aut.length = new int[v]; aut.position = new int[v]; aut.shift = new int[e]; return (aut); } /* * returns a new data structure for a trie with v vertices and e edges */ public static Graph newTrie(int v, int e) { Graph aut; aut = newAutomaton(v, e); aut.target = new int[e]; for (int i = 0; i < e; i++) aut.target[i] = UNDEFINED; aut.suffixLink = new int[v]; aut.length = new int[v]; aut.position = new int[v]; aut.shift = new int[e]; return (aut); } /* returns a new vertex for graph g */ public static int newVertex(Graph g) { int res = -1; if (g != null && g.vertexCounter <= g.vertexNumber) res = (g.vertexCounter++); return res; } /* returns the initial vertex of graph g */ public static int getInitial(Graph g) { return g.initial; } /* returns true if vertex v is terminal in graph g */ public static boolean isTerminal(Graph g, int v) { boolean res = false; if (g != null && g.terminal != null && v < g.vertexNumber) res = (g.terminal[v] == 1 ? true : false); return res; } /* set vertex v to be terminal in graph g */ public static void setTerminal(Graph g, int v) { if (g != null && g.terminal != null && v < g.vertexNumber) g.terminal[v] = 1; } /* * returns the target of edge from vertex v labelled by character c in * graph g */ public static int getTarget(Graph g, int v, int c) { int res = -1; if (g != null && g.target != null && v < g.vertexNumber && v * c < g.edgeNumber) res = (g.target[v * (g.edgeNumber / g.vertexNumber) + c]); return res; } /* * add the edge from vertex v to vertex t labelled by character c in * graph g */ public static void setTarget(Graph g, int v, int c, int t) { if (g != null && g.target != null && v < g.vertexNumber && v * c <= g.edgeNumber && t < g.vertexNumber) g.target[v * (g.edgeNumber / g.vertexNumber) + c] = t; } /* returns the suffix link of vertex v in graph g */ public static int getSuffixLink(Graph g, int v) { int res = -1; if (g != null && g.suffixLink != null && v < g.vertexNumber) res = (g.suffixLink[v]); return res; } /* * set the suffix link of vertex v to vertex s in graph g */ public static void setSuffixLink(Graph g, int v, int s) { if (g != null && g.suffixLink != null && v < g.vertexNumber && s < g.vertexNumber) g.suffixLink[v] = s; } /* returns the length of vertex v in graph g */ public static int getLength(Graph g, int v) { int res = -1; if (g != null && g.length != null && v < g.vertexNumber) res = (g.length[v]); return res; } /* set the length of vertex v to integer ell in graph g */ public static void setLength(Graph g, int v, int ell) { if (g != null && g.length != null && v < g.vertexNumber) g.length[v] = ell; } /* returns the position of vertex v in graph g */ public static int getPosition(Graph g, int v) { int res = -1; if (g != null && g.position != null && v < g.vertexNumber) res = (g.position[v]); return res; } /* set the length of vertex v to integer ell in graph g */ public static void setPosition(Graph g, int v, int p) { if (g != null && g.position != null && v < g.vertexNumber) g.position[v] = p; } /* * returns the shift of the edge from vertex v labelled by character c * in graph g */ public static int getShift(Graph g, int v, int c) { int res = -1; if (g != null && g.shift != null && v < g.vertexNumber && v * c < g.edgeNumber) res = (g.shift[v * (g.edgeNumber / g.vertexNumber) + c]); return res; } /* * set the shift of the edge from vertex v labelled by character c to * integer s in graph g */ public static void setShift(Graph g, int v, int c, int s) { if (g != null && g.shift != null && v < g.vertexNumber && v * c <= g.edgeNumber) g.shift[v * (g.edgeNumber / g.vertexNumber) + c] = s; } /* * copies all the characteristics of vertex source to vertex target in * graph g */ public static void copyVertex(Graph g, int target, int source) { if (g != null && target < g.vertexNumber && source < g.vertexNumber) { if (g.target != null) for (int i = 0; i < (g.edgeNumber / g.vertexNumber); i++) g.target[target * (g.edgeNumber / g.vertexNumber) + i] = g.target[source 1="(g.edgeNumber" 2="/" 3="g.vertexNumber)" 4="+" 5="i" language="*"][/source]; if (g.shift != null) for (int i = 0; i < (g.edgeNumber / g.vertexNumber); i++) g.shift[target * (g.edgeNumber / g.vertexNumber) + i] = g.shift[source 1="(g.edgeNumber" 2="/" 3="g.vertexNumber)" 4="+" 5="i" language="*"][/source]; if (g.terminal != null) g.terminal[target] = g.terminal[source][/source]; if (g.suffixLink != null) g.suffixLink[target] = g.suffixLink[source][/source]; if (g.length != null) g.length[target] = g.length[source][/source]; if (g.position != null) g.position[target] = g.position[source][/source]; } } } } |
Forward Dawg Matching algoritması
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
import java.util.ArrayList; import java.util.List; public class FDM { private static void buildSuffixAutomaton(char[] x, Graph aut) { int i, art, init, last, p, q, r, m = x.length; char c; init = Automata.getInitial(aut); art = Automata.newVertex(aut); Automata.setSuffixLink(aut, init, art); last = init; for (i = 0; i < m; ++i) { c = x[i]; p = last; q = Automata.newVertex(aut); Automata.setLength(aut, q, Automata.getLength(aut, p) + 1); Automata.setPosition(aut, q, Automata.getPosition(aut, p) + 1); while (p != init && Automata.getTarget(aut, p, c) == Automata.UNDEFINED) { Automata.setTarget(aut, p, c, q); Automata.setShift(aut, p, c, Automata.getPosition(aut, q) - Automata.getPosition(aut, p) - 1); p = Automata.getSuffixLink(aut, p); } if (Automata.getTarget(aut, p, c) == Automata.UNDEFINED) { Automata.setTarget(aut, init, c, q); Automata.setShift(aut, init, c, Automata.getPosition(aut, q) - Automata.getPosition(aut, init) - 1); Automata.setSuffixLink(aut, q, init); } else if (Automata.getLength(aut, p) + 1 == Automata.getLength( aut, Automata.getTarget(aut, p, c))) Automata.setSuffixLink(aut, q, Automata.getTarget(aut, p, c)); else { r = Automata.newVertex(aut); Automata.copyVertex(aut, r, Automata.getTarget(aut, p, c)); Automata.setLength(aut, r, Automata.getLength(aut, p) + 1); Automata.setSuffixLink(aut, Automata.getTarget(aut, p, c), r); Automata.setSuffixLink(aut, q, r); while (p != art && Automata.getLength(aut, Automata .getTarget(aut, p, c)) >= Automata.getLength( aut, r)) { Automata.setShift(aut, p, c, Automata.getPosition(aut, Automata.getTarget(aut, p, c)) - Automata.getPosition(aut, p) - 1); Automata.setTarget(aut, p, c, r); p = Automata.getSuffixLink(aut, p); } } last = q; } Automata.setTerminal(aut, last); while (last != init) { last = Automata.getSuffixLink(aut, last); Automata.setTerminal(aut, last); } } public static List<Integer> findAll(String pattern, String source) { char[] x = pattern.toCharArray(), y = source.toCharArray(); int j, init, ell, state, m = x.length, n = y.length; List<Integer> result = new ArrayList<Integer>(); Graph aut; /* Preprocessing */ aut = Automata.newSuffixAutomaton(2 * (m + 2), 2 * (m + 2) * 65536); buildSuffixAutomaton(x, aut); init = Automata.getInitial(aut); /* Searching */ ell = 0; state = init; for (j = 0; j < n; ++j) { if (Automata.getTarget(aut, state, y[j]) != Automata.UNDEFINED) { ++ell; state = Automata.getTarget(aut, state, y[j]); } else { while (state != init && Automata.getTarget(aut, state, y[j]) == Automata.UNDEFINED) state = Automata.getSuffixLink(aut, state); if (Automata.getTarget(aut, state, y[j]) != Automata.UNDEFINED) { ell = Automata.getLength(aut, state) + 1; state = Automata.getTarget(aut, state, y[j]); } else { ell = 0; state = init; } } if (ell == m) result.add(j - m + 1); } return result; } public static FDM compile(String pattern) { char[] x = pattern.toCharArray(); int init, m = x.length; Graph aut; aut = Automata.newSuffixAutomaton(2 * (m + 2), 2 * (m + 2) * 65536); buildSuffixAutomaton(x, aut); init = Automata.getInitial(aut); FDM fdm = new FDM(); fdm.aut = aut; fdm.m = m; fdm.init = init; return fdm; } public List<Integer> findAll(String source) { char[] y = source.toCharArray(); int j, ell, state, n = y.length; List<Integer> result = new ArrayList<Integer>(); ell = 0; state = init; for (j = 0; j < n; ++j) { if (Automata.getTarget(aut, state, y[j]) != Automata.UNDEFINED) { ++ell; state = Automata.getTarget(aut, state, y[j]); } else { while (state != init && Automata.getTarget(aut, state, y[j]) == Automata.UNDEFINED) state = Automata.getSuffixLink(aut, state); if (Automata.getTarget(aut, state, y[j]) != Automata.UNDEFINED) { ell = Automata.getLength(aut, state) + 1; state = Automata.getTarget(aut, state, y[j]); } else { ell = 0; state = init; } } if (ell == m) result.add(j - m + 1); } return result; } private Graph aut; private int m, init; private static class Graph { private int vertexNumber, edgeNumber, vertexCounter, initial; private int[] terminal, target, suffixLink, length, position, shift; } private static class Automata { private static final int UNDEFINED = -1; /* * returns a new data structure for a graph with v vertices and e edges */ public static Graph newGraph(int v, int e) { Graph g = new Graph(); g.vertexNumber = v; g.edgeNumber = e; g.initial = 0; g.vertexCounter = 1; return (g); } /* * returns a new data structure for a automaton with v vertices and e * edges */ public static Graph newAutomaton(int v, int e) { Graph aut; aut = newGraph(v, e); aut.target = new int[e]; ; aut.terminal = new int[v]; return (aut); } /* * returns a new data structure for a suffix automaton with v vertices * and e edges */ public static Graph newSuffixAutomaton(int v, int e) { Graph aut; aut = newAutomaton(v, e); aut.target = new int[e]; for (int i = 0; i < e; i++) aut.target[i] = UNDEFINED; aut.suffixLink = new int[v]; aut.length = new int[v]; aut.position = new int[v]; aut.shift = new int[e]; return (aut); } /* * returns a new data structure for a trie with v vertices and e edges */ public static Graph newTrie(int v, int e) { Graph aut; aut = newAutomaton(v, e); aut.target = new int[e]; for (int i = 0; i < e; i++) aut.target[i] = UNDEFINED; aut.suffixLink = new int[v]; aut.length = new int[v]; aut.position = new int[v]; aut.shift = new int[e]; return (aut); } /* returns a new vertex for graph g */ public static int newVertex(Graph g) { int res = -1; if (g != null && g.vertexCounter <= g.vertexNumber) res = (g.vertexCounter++); return res; } /* returns the initial vertex of graph g */ public static int getInitial(Graph g) { return g.initial; } /* returns true if vertex v is terminal in graph g */ public static boolean isTerminal(Graph g, int v) { boolean res = false; if (g != null && g.terminal != null && v < g.vertexNumber) res = (g.terminal[v] == 1 ? true : false); return res; } /* set vertex v to be terminal in graph g */ public static void setTerminal(Graph g, int v) { if (g != null && g.terminal != null && v < g.vertexNumber) g.terminal[v] = 1; } /* * returns the target of edge from vertex v labelled by character c in * graph g */ public static int getTarget(Graph g, int v, int c) { int res = -1; if (g != null && g.target != null && v < g.vertexNumber && v * c < g.edgeNumber) res = (g.target[v * (g.edgeNumber / g.vertexNumber) + c]); return res; } /* * add the edge from vertex v to vertex t labelled by character c in * graph g */ public static void setTarget(Graph g, int v, int c, int t) { if (g != null && g.target != null && v < g.vertexNumber && v * c <= g.edgeNumber && t < g.vertexNumber) g.target[v * (g.edgeNumber / g.vertexNumber) + c] = t; } /* returns the suffix link of vertex v in graph g */ public static int getSuffixLink(Graph g, int v) { int res = -1; if (g != null && g.suffixLink != null && v < g.vertexNumber) res = (g.suffixLink[v]); return res; } /* * set the suffix link of vertex v to vertex s in graph g */ public static void setSuffixLink(Graph g, int v, int s) { if (g != null && g.suffixLink != null && v < g.vertexNumber && s < g.vertexNumber) g.suffixLink[v] = s; } /* returns the length of vertex v in graph g */ public static int getLength(Graph g, int v) { int res = -1; if (g != null && g.length != null && v < g.vertexNumber) res = (g.length[v]); return res; } /* set the length of vertex v to integer ell in graph g */ public static void setLength(Graph g, int v, int ell) { if (g != null && g.length != null && v < g.vertexNumber) g.length[v] = ell; } /* returns the position of vertex v in graph g */ public static int getPosition(Graph g, int v) { int res = -1; if (g != null && g.position != null && v < g.vertexNumber) res = (g.position[v]); return res; } /* set the length of vertex v to integer ell in graph g */ public static void setPosition(Graph g, int v, int p) { if (g != null && g.position != null && v < g.vertexNumber) g.position[v] = p; } /* * returns the shift of the edge from vertex v labelled by character c * in graph g */ public static int getShift(Graph g, int v, int c) { int res = -1; if (g != null && g.shift != null && v < g.vertexNumber && v * c < g.edgeNumber) res = (g.shift[v * (g.edgeNumber / g.vertexNumber) + c]); return res; } /* * set the shift of the edge from vertex v labelled by character c to * integer s in graph g */ public static void setShift(Graph g, int v, int c, int s) { if (g != null && g.shift != null && v < g.vertexNumber && v * c <= g.edgeNumber) g.shift[v * (g.edgeNumber / g.vertexNumber) + c] = s; } /* * copies all the characteristics of vertex source to vertex target in * graph g */ public static void copyVertex(Graph g, int target, int source) { if (g != null && target < g.vertexNumber && source < g.vertexNumber) { if (g.target != null) for (int i = 0; i < (g.edgeNumber / g.vertexNumber); i++) g.target[target * (g.edgeNumber / g.vertexNumber) + i] = g.target[source 1="(g.edgeNumber" 2="/" 3="g.vertexNumber)" 4="+" 5="i" language="*"][/source]; if (g.shift != null) for (int i = 0; i < (g.edgeNumber / g.vertexNumber); i++) g.shift[target * (g.edgeNumber / g.vertexNumber) + i] = g.shift[source 1="(g.edgeNumber" 2="/" 3="g.vertexNumber)" 4="+" 5="i" language="*"][/source]; if (g.terminal != null) g.terminal[target] = g.terminal[source][/source]; if (g.suffixLink != null) g.suffixLink[target] = g.suffixLink[source][/source]; if (g.length != null) g.length[target] = g.length[source][/source]; if (g.position != null) g.position[target] = g.position[source][/source]; } } } } |
Galil-Giancarlo algoritması
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
import java.util.ArrayList; import java.util.List; public class GG { private static int preColussi(char[] x, int[] h, int[] next, int[] shift) { int i, k, nd, q, r = 0, s, m = (x.length - 1); int[] hmax = new int[x.length]; int[] kmin = new int[x.length]; int[] nhd0 = new int[x.length]; int[] rmin = new int[x.length]; /* Computation of hmax */ i = k = 1; do { while (x[i] == x[i - k]) i++; hmax[k] = i; q = k + 1; while (hmax[q - k] + k < i) { hmax[q] = hmax[q - k] + k; q++; } k = q; if (k == i + 1) i = k; } while (k <= m); /* Computation of kmin */ for (i = 0; i < kmin.length; i++) kmin[i] = 0; for (i = m; i >= 1; --i) if (hmax[i] < m) kmin[hmax[i]] = i; /* Computation of rmin */ for (i = m - 1; i >= 0; --i) { if (hmax[i + 1] == m) r = i + 1; if (kmin[i] == 0) rmin[i] = r; else rmin[i] = 0; } /* Computation of h */ s = -1; r = m; for (i = 0; i < m; ++i) if (kmin[i] == 0) h[--r] = i; else h[++s] = i; nd = s; /* Computation of shift */ for (i = 0; i <= nd; ++i) shift[i] = kmin[h[i]]; for (i = nd + 1; i < m; ++i) shift[i] = rmin[h[i]]; shift[m] = rmin[0]; /* Computation of nhd0 */ s = 0; for (i = 0; i < m; ++i) { nhd0[i] = s; if (kmin[i] > 0) ++s; } /* Computation of next */ for (i = 0; i <= nd; ++i) next[i] = nhd0[h[i] - kmin[h[i]]]; for (i = nd + 1; i < m; ++i) next[i] = nhd0[m - rmin[h[i]]]; next[m] = nhd0[m - rmin[h[m - 1]]]; return (nd); } public static List<Integer> findAll(String pattern, String source) { char[] ptrn = pattern.toCharArray(), y = source.toCharArray(); char[] x = new char[ptrn.length + 1]; System.arraycopy(ptrn, 0, x, 0, ptrn.length); int i, j, k, ell, last, nd, m = ptrn.length, n = y.length; List<Integer> result = new ArrayList<Integer>(); int[] h = new int[x.length]; int[] next = new int[x.length]; int[] shift = new int[x.length]; boolean heavy = false; for (ell = 0; x[ell] == x[ell + 1]; ell++) ; if (ell == m - 1) /* Searching for a power of a single character */ for (j = ell = 0; j < n; ++j) if (x[0] == y[j]) { ++ell; if (ell >= m) result.add(j - m + 1); } else ell = 0; else { /* Preprocessing */ nd = preColussi(x, h, next, shift); /* Searching */ i = j = 0; last = -1; while (j <= n - m) { if (heavy && i == 0) { k = last - j + 1; while (x[0] == y[j + k]) k++; if (k <= ell || x[ell + 1] != y[j + k]) { i = 0; j += (k + 1); last = j - 1; } else { i = 1; last = j + k; j = last - (ell + 1); } heavy = false; } else { while (i < m && last < j + h[i] && x[h[i]] == y[j + h[i]]) ++i; if (i >= m || last >= j + h[i]) { result.add(j); i = m; } if (i > nd) last = j + m - 1; j += shift[i]; i = next[i]; } heavy = (j > last ? false : true); } } return result; } public static GG compile(String pattern) { char[] ptrn = pattern.toCharArray(); char[] x = new char[ptrn.length + 1]; System.arraycopy(ptrn, 0, x, 0, ptrn.length); int nd, m = ptrn.length; int[] h = new int[x.length]; int< |