// Mot.java import java.util.Enumeration; import java.util.Vector; /** * Classe permettant de manipuler des mots * @see Lettre * @author Maxime Crochemore * @author Christophe Hancart * @author Thierry Lecroq */ public class Mot { /** Un mot est un tableau de lettres */ private Lettre[] mot; /** La longueur d'un mot est son nombre de lettres */ private int longueur; /** Construit un mot vide */ Mot() { this.longueur = 0; this.mot = new Lettre[0]; } /** Construit un mot à partir d'un objet String */ Mot(String mot) { this.longueur = mot.length(); this.mot = new Lettre[this.longueur]; for (int i = 0; i < this.longueur; ++i) this.mot[i] = new Lettre(mot.charAt(i)); } /** Construit un mot ne contenant qu'une seule lettre */ Mot(Lettre a) { this.longueur = 1; this.mot = new Lettre[1]; this.mot[0] = a; } /** Retourne le tableau de lettres du mot */ public Lettre[] getMot() { return this.mot; } /** Fixe la valeur du tableau de lettres */ private void setMot(Lettre[] mot) { this.mot = mot; } /** Retourne la longueur du mot */ public int getLongueur() { return this.longueur; } /** Fixe la longueur du mot */ private void setLongueur(int longueur) { this.longueur = longueur; } public String toString() { String resultat = ""; for (int i = 0; i < this.longueur; i++) resultat = resultat + this.lettreA(i); return resultat; } boolean egal(int j, Mot x) { for (int i = 0; i < x.getLongueur(); ++i) if (!this.lettreA(i + j).equals(x.lettreA(i))) return false; return true; } /** Retourne la lettre à une position */ Lettre lettreA(int i) { return this.mot[i]; } public Object clone() { Mot w = new Mot(); w.mot = (Lettre [])this.mot.clone(); w.longueur = this.getLongueur(); return w; } /** Teste si la lettre apparait dans le mot */ public boolean contient(Lettre a) { int m = this.getLongueur(); for (int i = 0; i <= m - 1; ++i) if (this.lettreA(i).equals(a)) return true; return false; } /** Ajoute la lettre en premiere position et decale les autres */ public void ajouterAuDebut(Lettre a) { int m = this.getLongueur(); Lettre[] w = new Lettre[m + 1]; System.arraycopy(this.mot, 0, w, 1, m); w[0] = a; this.mot = w; this.longueur = m + 1; } public Mot getLettres(int i, int j) { Mot x = new Mot(); try { int ell = j - i + 1; Lettre[] mot = new Lettre[ell]; System.arraycopy(this.mot, i, mot, 0, ell); x.setLongueur(ell); x.setMot(mot); } catch (Exception e) {} return x; } public Mot concat(Mot y) { int m = this.getLongueur(), n = y.getLongueur(); Lettre[] mot = new Lettre[m + n]; System.arraycopy(this.mot, 0, mot, 0, m); System.arraycopy(y.getMot(), 0, mot, m, n); Mot x = new Mot(); x.setLongueur(m + n); x.setMot(mot); return x; } /** * Recherche naive * @param x le mot à rechercher */ public Vector localiserNaivement(Mot x) { Vector v = new Vector(); int m, n; m = x.getLongueur(); n = this.getLongueur(); for (int j = 0; j <= n - m; ++j) if (this.egal(j, x)) v.addElement(new Integer(j)); return v; } /** * Calcule la table de dernière occurrence */ public int[] derniereOccurrence(Alphabet alphabet) { int[] dernOcc; int m; m = this.getLongueur(); dernOcc = new int[alphabet.getCard()]; Enumeration e = alphabet.elements(); while (e.hasMoreElements()) dernOcc[alphabet.rang((Lettre)e.nextElement())] = m; for (int k = 0; k <= m - 2; ++k) dernOcc[alphabet.rang(this.lettreA(k))] = m - 1 - k; return dernOcc; } /** * Appelle le calcul de la table de dernière occurrence et * recherche rapide */ public Vector localiserRapidement(Mot x, Alphabet alphabet) { Vector v = new Vector(); int[] dernOcc = x.derniereOccurrence(alphabet); int m, n; m = x.getLongueur(); n = this.getLongueur(); for (int j = m - 1; j < n; j += dernOcc[alphabet.rang(this.lettreA(j))]) if (this.egal(j - m + 1, x)) v.addElement(new Integer(j - m + 1)); return v; } public Vector localiserMotsCourts(EnsembleDeMots x, Alphabet alphabet) { Vector v = new Vector(); PetitAutomate pA = x.petitAutomate(alphabet); int init = pA.getInit(); int[] masq = pA.getMasq(); int term = pA.getTerm(); int r = 0; int n = this.getLongueur(); for (int j = 0; j < n; ++j) { r = (init | (r << 1)) & masq[alphabet.rang(this.lettreA(j))]; if ((r & term) != 0) v.addElement(new Integer(j)); } return v; } public int[] bords() { int m = this.getLongueur(); int[] bord = new int[m]; int i = 0; for (int j = 1; j <= m - 1; ++j) { bord[j - 1] = i; while (i >= 0 && ! this.lettreA(j).equals(this.lettreA(i))) if (i == 0) i = -1; else i = bord[i - 1]; ++i; } bord[m - 1] = i; return bord; } public int[] prefixes() { int m = this.getLongueur(); int[] pref = new int[m]; int g = 0, f = 0; pref[0] = m; for (int i = 1; i <= m - 1; ++i) if (i < g && pref[i - f] < g - i) pref[i] = pref[i - f]; else { if (i > g) g = i; f = i; while (g < m && this.lettreA(g).equals(this.lettreA(g - f))) ++g; pref[i] = g - f; } return pref; } public int[] bonPrefixe() { int m = this.getLongueur(); int[] bonPref = new int[m + 1]; int i = 0; bonPref[0] = -1; for (int j = 1; j <= m - 1; ++j) { // Ici, mot[0..i-1] = Bord(mot[0..j-1]) bonPref[j] = i; while (i >= 0 && ! this.lettreA(j).equals(this.lettreA(i))) i = bonPref[i]; ++i; } bonPref[m] = i; return bonPref; } public int[] meilleurPrefixe() { int m = this.getLongueur(); int[] meilPref = new int[m + 1]; int i = 0; meilPref[0] = -1; for (int j = 1; j <= m - 1; ++j) { // Ici, mot[0..i-1] = Bord(mot[0..j-1]) if (this.lettreA(j).equals(this.lettreA(i))) meilPref[j] = meilPref[i]; else { meilPref[j] = i; do { i = meilPref[i]; } while (i >= 0 && ! this.lettreA(j).equals(this.lettreA(i))); } ++i; } meilPref[m] = i; return meilPref; } public Vector localiserSelonPrefixe(Mot x, int[] pi) { Vector v = new Vector(); int i = 0; int m = x.getLongueur(); int n = this.getLongueur(); for (int j = 0; j < n; ++j) { // Ici, x[0..i-1] est le plus long préfixe de x // qui est également un suffixe de y if (i == m) i = pi[m]; while (i >= 0 && ! this.lettreA(j).equals(x.lettreA(i))) i = pi[i]; ++i; if (i == m) v.addElement(new Integer(j - m + 1)); } return v; } public Automate aluComplet(Alphabet alphabet) { Automate automate = new Automate(); Etat q0 = automate.getInitial(); Etat p, r, t; Enumeration e = alphabet.elements(); while (e.hasMoreElements()) q0.setCible((Lettre)e.nextElement(), q0); t = q0; for (int i = 0; i < this.getLongueur(); ++i) { p = new Etat(); r = t.getCible(this.lettreA(i)); t.setCible(this.lettreA(i), p); p.copieCibles(r); t = p; } t.setTerminal(true); return automate; } public Automate alpParDefault() { Automate automate = new Automate(); Etat q0 = automate.getInitial(), p, r, t = q0; int m = this.getLongueur(); for (int i = 0; i <= m - 1; ++i) { p = new Etat(); r = t.getCible(this.lettreA(i)); if (r == null) r = q0; t.setCible(this.lettreA(i), p); p.copieCibles(r); t = p; } t.setTerminal(true); return automate; } public Vector laDeterministe(Automate automate) { Etat r = automate.getInitial(); Vector v = new Vector(); int n = this.getLongueur(); for (int j = 0; j <= n - 1; ++j) { r = r.getCible(this.lettreA(j)); if (r.isTerminal()) v.addElement(new Integer(j)); } return v; } public Vector laDeterministeParSuppleance(EnsembleDeMots x, Alphabet alphabet) { Automate automate = x.alpParSuppleance(alphabet); Etat r = automate.getInitial(); Vector v = new Vector(); int n = this.getLongueur(); for (int j = 0; j <= n - 1; ++j) { r = r.cibleParSuppleance(automate, this.lettreA(j)); if (r.isTerminal()) v.addElement(new Integer(j)); } return v; } public int[] suffixes() { int m = this.getLongueur(); int suff[] = new int[m]; int f = 0, g = m - 1; suff[m - 1] = m; for (int 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 && this.lettreA(g).equals(this.lettreA(g + m - 1 - f))) --g; suff[i] = f - g; } return suff; } public int[] bonSuffixe(int[] suff) { int m = this.getLongueur(); int bonSuff[] = new int[m]; for (int i = m - 2, j = 0; i >= -1; --i) if (i == -1 || suff[i] == i + 1) while (j < m - 1 - i) { bonSuff[j] = m - 1 - i; ++j; } for (int i = 0; i <= m - 2; ++i) bonSuff[m - 1 - suff[i]] = m - 1 - i; return bonSuff; } public Vector lsSansMemoireFaible(Mot x, int[] bonSuff) { Vector v = new Vector(); int m = x.getLongueur(); int n = this.getLongueur(); int i, j = m - 1; while (j < n) { i = m - 1; while (i >= 0 && x.lettreA(i).equals(this.lettreA(j - m + 1 + i))) --i; if (i < 0) v.addElement(new Integer(j)); if (i < 0) j += bonSuff[0]; else j += bonSuff[i]; } return v; } public Vector lsSansMemoireFaibleLineaire(Mot x, int[] bonSuff) { Vector v = new Vector(); int m = x.getLongueur(); int n = this.getLongueur(); int i, j = m - 1, ell = 0; while (j < n) { i = m - 1; while (i >= ell && x.lettreA(i).equals(this.lettreA(j - m + 1 + i))) --i; if (i < 0) v.addElement(new Integer(j)); if (i < ell) { ell = m - bonSuff[0]; j += bonSuff[0]; } else { ell = 0; j += bonSuff[i]; } } return v; } public Vector lsUneMemoireFaible(Mot x, int[] bonSuff) { Vector v = new Vector(); int m = x.getLongueur(); int n = this.getLongueur(); int i, j = m - 1, dec = 0, mem = 0, turbo; while (j < n) { i = m - 1; while (i >= 0 && x.lettreA(i).equals(this.lettreA(j - m + 1 + i))) if (i == m - dec) i -= (mem - 1); // Saut else --i; if (i < 0) v.addElement(new Integer(j)); if (i < 0) { dec = bonSuff[0]; mem = m - dec; } else { turbo = mem - m + 1 + i; if (turbo <= bonSuff[i]) { dec = bonSuff[i]; mem = Math.min(m - dec, m - i); } else { dec = Math.max(turbo, m - 1 - i); mem = 0; } } j += dec; // Décalage } return v; } public Vector lsPlusieursMemoiresFaible(Mot x, int[] suff, int[] bonSuff) { Vector v = new Vector(); int m = x.getLongueur(); int n = this.getLongueur(); int i, j = m - 1, k, s; int[] skip = new int[n]; j = m - 1; while (j < n) { i = m - 1; while (i >= 0) if (skip[j - m + 1 + i] > 0) { k = skip[j - m + 1 + i]; s = suff[i]; if (s != k) { i -= Math.min(s, k); break; } else i -= k; // Saut } else if (x.lettreA(i).equals(this.lettreA(j - m + 1 + i))) --i; else break; if (i < 0) v.addElement(new Integer(j)); if (i < 0) { skip[j] = m; j += bonSuff[0]; } else { skip[j] = m - 1 - i; j += bonSuff[i]; } } return v; } public Couple rechercheSimple(Mot[] liste) { int d = -1, i, ell, m = this.getLongueur(), n = liste.length, f = n; while (d + 1 < f) { // Invariant : liste[d] < x < liste[f] i = (d + f)/2; ell = this.llpc(liste[i]); if (ell == m && ell == liste[i].getLongueur()) return new Couple(new Integer(i), new Integer(i)); else if (ell == liste[i].getLongueur() || (ell != m && liste[i].lettreA(ell).inferieurA(this.lettreA(ell)))) d = i; else f = i; } return new Couple(new Integer(d), new Integer(f)); } public int llpc(Mot y) { int i = 0, m = this.getLongueur(), n = y.getLongueur(); while (i < m && i < n && this.lettreA(i).equals(y.lettreA(i))) ++i; return i; } public Automate arbreSuffixes() { Automate automate = new Automate(); Couple couple; Etat fourche, p, q; int k, n = this.getLongueur(); for (int i = 0; i <= n - 1; ++i) { couple = this.descLente(automate.getInitial(), i); fourche = (Etat)couple.getComp1(); k = ((Integer)couple.getComp2()).intValue(); p = fourche; for (int j = k; j <= n - 1; ++j) { q = new Etat(); p.setCible(this.lettreA(j), q); p = q; } p.setSortie(i); } automate.getInitial().setSortie(n); return automate; } private Couple descLente(Etat p, int k) { int n = this.getLongueur(); while (k < n && p.getCible(this.lettreA(k)) != null) { p = p.getCible(this.lettreA(k)); ++k; } return new Couple(p, new Integer(k)); } private Couple descLenteBis(Etat p, int k, Automate automate) { int n = this.getLongueur(); Etat e, f, q; while (k < n && p.getCible(this.lettreA(k)) != null) { q = p.getCible(this.lettreA(k)); e = p; f = q; while (e != automate.getInitial() && f.getLs() == null) { f.setLs(e.getLs().getCible(this.lettreA(k))); e = e.getLs(); f = f.getLs(); } if (e == automate.getInitial()) f.setLs(automate.getInitial()); p = q; ++k; } return new Couple(p, new Integer(k)); } public Automate arbreSuffixesBis() { Automate automate = new Automate(); Couple couple; Etat fourche = automate.getInitial(), p, q; int k = 0, n = this.getLongueur(); automate.getInitial().setLs(automate.getInitial()); for (int i = 0; i <= n - 1; ++i) { k = Math.max(k, i); couple = this.descLenteBis(fourche.getLs(), k, automate); fourche = (Etat)couple.getComp1(); k = ((Integer)couple.getComp2()).intValue(); p = fourche; for (int j = k; j <= n - 1; ++j) { q = new Etat(); p.setCible(this.lettreA(j), q); p = q; } p.setSortie(i); } automate.getInitial().setSortie(n); return automate; } public Automate autoSuffixes() { Automate automate = new Automate(); Etat p; int n = this.getLongueur(); automate.getInitial().setL(0); automate.getInitial().setF(null); automate.setDernier(automate.getInitial()); for (int i = 0; i <= n - 1; ++i) this.lettreA(i).extension(automate); p = automate.getDernier(); do { p.setTerminal(true); p = p.getF(); } while (p != null); return automate; } public Automate interdits(Automate sy, Alphabet alphabet) { Automate automate = new Automate(); Couple couple; Etat p, pp, qp; File ell = new File(); Lettre a; Vector atteint = new Vector(); ell.enfiler(new Couple(sy.getInitial(), automate.getInitial())); atteint.addElement(sy.getInitial()); while (!ell.estFileVide()) { couple = (Couple)ell.defilement(); p = (Etat)couple.getComp1(); pp = (Etat)couple.getComp2(); Enumeration e = alphabet.elements(); while (e.hasMoreElements()) { a = (Lettre)e.nextElement(); if (p.getCible(a) == null && (p == sy.getInitial() || p.getF().getCible(a) != null)) { qp = new Etat(); qp.setTerminal(true); pp.setCible(a, qp); } else if (p.getCible(a) != null && !atteint.contains(p.getCible(a))) { qp = new Etat(); pp.setCible(a, qp); ell.enfiler(new Couple(p.getCible(a), qp)); atteint.addElement(p.getCible(a)); } } } return automate; } public int[] longueurDesFacteurs(Automate sx) { Etat p = sx.getInitial(); int ell = 0, n = this.getLongueur(); int[] t = new int[n]; for (int i = 0; i <= n - 1; ++i) { if (p.getCible(this.lettreA(i)) != null) { ++ell; p = p.getCible(this.lettreA(i)); } else { do { p = p.getF(); } while (p != null && p.getCible(this.lettreA(i)) == null); if (p != null) { ell = p.getL() + 1; p = p.getCible(this.lettreA(i)); } else { ell = 0; p = sx.getInitial(); } } t[i] = ell; } return t; } public Table calculGeneriqueBis(Mot y) { int m = this.getLongueur(); int n = y.getLongueur(); Table t = new Table(m, n); t.set(-1, -1, 0); for (int i = 0; i <= m - 1; ++i) t.set(i, -1, t.get(i - 1, -1) + this.lettreA(i).del()); for (int j = 0; j <= n - 1; ++j) t.set(-1, j, t.get(-1, j - 1) + y.lettreA(j).ins()); for (int j = 0; j <= n - 1; ++j) for (int i = 0; i <= m - 1; ++i) t.set(i, j, Math.min( t.get(i - 1, j - 1) + this.lettreA(i).sub(y.lettreA(j)), Math.min( t.get(i - 1, j) + this.lettreA(i).del(), t.get(i, j - 1) + y.lettreA(j).ins()))); return t; } public int calculGenerique(Mot y) { Table t = this.calculGeneriqueBis(y); return t.get(this.getLongueur() - 1, y.getLongueur() - 1); } public Alignement unAlignement(Mot y, Table t) { Alignement z = new Alignement(); int m = this.getLongueur(), n = y.getLongueur(), i = m - 1, j = n - 1; while (i != -1 && j != -1) if (t.get(i, j) == t.get(i - 1, j - 1) + this.lettreA(i).sub(y.lettreA(j))) { z.ajouterAuDebut(this.lettreA(i), y.lettreA(j)); --i; --j; } else if (t.get(i, j) == t.get(i - 1, j) + this.lettreA(i).del()) { z.ajouterAuDebut(this.lettreA(i), new Lettre('-')); --i; } else { z.ajouterAuDebut(new Lettre('-'), y.lettreA(j)); --j; } while (i != -1) { z.ajouterAuDebut(this.lettreA(i), new Lettre('-')); --i; } while (j != -1) { z.ajouterAuDebut(new Lettre('-'), y.lettreA(j)); --j; } return z; } public void lesAlignements(Mot y, Table t) { this.la(this.getLongueur() - 1, y.getLongueur() - 1, new Alignement(), y, t); } public void la(int i, int j, Alignement z, Mot y, Table t) { if (i != -1 && j != -1 && t.get(i, j) == t.get(i - 1, j - 1) + this.lettreA(i).sub(y.lettreA(j))) { Alignement zz = (Alignement)z.clone(); zz.ajouterAuDebut(this.lettreA(i), y.lettreA(j)); la(i - 1, j - 1, zz, y, t); } if (i != -1 && t.get(i, j) == t.get(i - 1, j) + this.lettreA(i).del()) { Alignement zz = (Alignement)z.clone(); zz.ajouterAuDebut(this.lettreA(i), new Lettre('-')); la(i - 1, j, zz, y, t); } if (j != -1 && t.get(i, j) == t.get(i, j - 1) + y.lettreA(j).ins()) { Alignement zz = (Alignement)z.clone(); zz.ajouterAuDebut(new Lettre('-'), y.lettreA(j)); la(i, j - 1, zz, y, t); } if (i == -1 && j == -1) System.out.println(z); } public Automate autoAlignOpt(Mot y, Table t) { Automate automate = new Automate(); int m = this.getLongueur(), n = y.getLongueur(); TableDEtats e = new TableDEtats(m, n); e.set(-1, -1, automate.getInitial()); e.set(m - 1, n - 1, new Etat()); e.get(m - 1, n - 1).setTerminal(true); this.aa(m - 1, n - 1, y, t, e); return automate; } public void aa(int i, int j, Mot y, Table t, TableDEtats e) { if (i != -1 && j != -1 && t.get(i, j) == t.get(i - 1, j - 1) + this.lettreA(i).sub(y.lettreA(j))) { if (e.get(i - 1, j - 1) == null) { e.set(i - 1, j - 1, new Etat()); aa(i - 1, j - 1, y, t, e); } e.get(i - 1, j - 1).setCible(new Couple(this.lettreA(i), y.lettreA(j)), e.get(i, j)); } if (i != -1 && t.get(i, j) == t.get(i - 1, j) + this.lettreA(i).del()) { if (e.get(i - 1, j) == null) { e.set(i - 1, j, new Etat()); aa(i - 1, j, y, t, e); } e.get(i - 1, j).setCible(new Couple(this.lettreA(i), new Lettre('-')), e.get(i, j)); } if (j != -1 && t.get(i, j) == t.get(i, j - 1) + y.lettreA(j).ins()) { if (e.get(i, j - 1) == null) { e.set(i, j - 1, new Etat()); aa(i, j - 1, y, t, e); } e.get(i, j - 1).setCible(new Couple(new Lettre('-'), y.lettreA(j)), e.get(i, j)); } } public Table smcSimpleBis(Mot y) { int m = this.getLongueur(), n = y.getLongueur(); Table s = new Table(m, n); for (int j = 0; j <= n - 1; ++j) for (int i = 0; i <= m - 1; ++i) if (this.lettreA(i).equals(y.lettreA(j))) s.set(i, j, s.get(i - 1, j - 1) + 1); else s.set(i, j, Math.max(s.get(i - 1, j), s.get(i, j - 1))); return s; } public int smcSimple(Mot y) { Table s = this.smcSimpleBis(y); return s.get(this.getLongueur() - 1, y.getLongueur() - 1); } public Mot unPlusLongSousMotCommun(Mot y, Table s) { Mot z = new Mot(); int m = this.getLongueur(), n = y.getLongueur(), i = m - 1, j = n - 1; while (i != -1 && j != -1) if (this.lettreA(i).equals(y.lettreA(j))) { z.ajouterAuDebut(this.lettreA(i)); --i; --j; } else if (s.get(i - 1, j) > s.get(i, j - 1)) --i; else --j; return z; } public int[] smcColonne(Mot y, int n) { int m = this.getLongueur(); int[] c, c1 = new int[m + 1], c2 = new int[m + 1]; for (int j = 0; j <= n - 1; ++j) { for (int i = 0; i <= m - 1; ++i) if (this.lettreA(i).equals(y.lettreA(j))) c2[i + 1] = c1[i] + 1; else c2[i + 1] = Math.max(c1[i + 1], c2[i]); c = c1; c1 = c2; c2 = c; } return c1; } public Mot smc(Mot y) { Mot aux1, aux2, u, v; int k, m = this.getLongueur(), n = y.getLongueur(); int[] c, c1, c2 = new int[m + 1], p, p1 = new int[m + 1], p2 = new int[m + 1]; if (m == 1 && y.contient(this.lettreA(0))) return new Mot(this.lettreA(0)); else if (n == 1 && this.contient(y.lettreA(0))) return new Mot(y.lettreA(0)); else if (m == 0 || m == 1 || n == 0 || n == 1) return new Mot(); c1 = this.smcColonne(y, n/2); for (int i = -1; i <= m - 1; ++i) p1[i + 1] = i + 1; for (int j = n/2; j <= n - 1; ++j) { for (int i = 0; i <= m - 1; ++i) if (this.lettreA(i).equals(y.lettreA(j))) { c2[i + 1] = c1[i] + 1; p2[i + 1] = p1[i]; } else if (c1[i + 1] > c2[i]) { c2[i + 1] = c1[i + 1]; p2[i + 1] = p1[i + 1]; } else { c2[i + 1] = c2[i]; p2[i + 1] = p2[i]; } c = c1; c1 = c2; c2 = c; p = p1; p1 = p2; p2 = p; } k = p1[m]; aux1 = this.getLettres(0, k - 1); aux2 = y.getLettres(0, n/2 - 1); u = aux1.smc(aux2); aux1 = this.getLettres(k, m - 1); aux2 = y.getLettres(n/2, n - 1); v = aux1.smc(aux2); return u.concat(v); } public int breche(Mot y, int g, int h) { int m = this.getLongueur(), n = y.getLongueur(), t; Table tt = new Table(m, n), td = new Table(m, n), ti = new Table(m, n); int inf = ~0 >>> 1; for (int i = -1; i <= m - 1; ++i) { td.set(i, -1, inf); ti.set(i, -1, inf); } tt.set(0, -1, g); for (int i = 1; i <= m - 1; ++i) tt.set(i, -1, tt.get(i - 1, -1) + h); tt.set(-1, 0, g); for (int j = 1; j <= n - 1; ++j) tt.set(-1, j, tt.get(-1, j - 1) + h); for (int j = 0; j <= n - 1; ++j) { td.set(-1, j, inf); ti.set(-1, j, inf); for (int i = 0; i <= m - 1; ++i) { td.set(i, j, Math.min(td.get(i - 1, j) + h, tt.get(i - 1, j) +g)); ti.set(i, j, Math.min(ti.get(i, j - 1) + h, tt.get(i, j - 1) +g)); t = tt.get(i - 1, j - 1) + this.lettreA(i).sub(y.lettreA(j)); tt.set(i, j, Math.min(t, Math.min(td.get(i, j), ti.get(i, j)))); } } return tt.get(m - 1, n - 1); } public Table alignementLocal(Mot y) { int m = this.getLongueur(), n = y.getLongueur(); Table s = new Table(m, n); for (int j = 0; j <= n - 1; ++j) for (int i = 0; i <= m - 1; ++i) s.set(i, j, Math.max(Math.max(0, s.get(i - 1, j - 1) + this.lettreA(i).sub(y.lettreA(j))), Math.max(s.get(i - 1, j) + this.lettreA(i).del(), s.get(i, j - 1) + y.lettreA(j).ins()))); return s; } public Vector lDiffDyn(Mot x, int k) { int m = x.getLongueur(), n = this.getLongueur(); Table r = new Table(m, n); Vector v = new Vector(); for (int i = 0; i <= m - 1; ++i) r.set(i, -1, i + x.lettreA(i).del()); for (int j = 0; j <= n - 1; ++j) { for (int i = 0; i <= m - 1; ++i) r.set(i, j, Math.min(r.get(i - 1, j - 1) + x.lettreA(i).sub(this.lettreA(j)), Math.min(r.get(i - 1, j) + x.lettreA(i).del(), r.get(i, j - 1) + this.lettreA(j).ins()))); if (r.get(m - 1, j) <= k) v.addElement(new Integer(j)); } return v; } public Vector lDiffElag(Mot x, int k) { int m = x.getLongueur(), n = this.getLongueur(), p; int[] c, c1 = new int[m], c2 = new int[m]; Vector v = new Vector(); for (int i = -1; i <= k - 1; ++i) c1[i + 1] = i + 1; p = k; for (int j = 0; j <= n - 1; ++j) { c2[0] = 0; for (int i = 0; i <= p; ++i) if (x.lettreA(i).equals(this.lettreA(j))) c2[i + 1] = c1[i]; else c2[i + 1] = Math.min(c1[i], Math.min(c2[i], c1[i + 1])) + 1; c = c1; c1 = c2; c2 = c; while (c1[p + 1] > k) --p; if (p == m - 1) v.addElement(new Integer(j)); p = Math.min(p + 1, m - 1); } return v; } public Vector lDiffDiag(Mot x, int k) { int m = x.getLongueur(), n = this.getLongueur(), p; Table tl = new Table(k, n - m + k + 2); Vector v = new Vector(); return v; } public Vector lInegalites(Mot x, int k, File[] fg) { File ff = new File(), fj; int f = -1, g = -1, m = x.getLongueur(), n = this.getLongueur(), p; Vector v = new Vector(); for (int j = 0; j <= n - m; ++j) { if (ff.getLongueur() > 0 && ((Integer)ff.tete()).intValue() == j - f - 1) ff.defiler(); if (j <= g) fj = this.inegFusion(f, j, g, ff, fg[j - f], x, k); else fj = new File(); if (fj.getLongueur() <= k) { ff = fj; f = j; do { ++g; if (!x.lettreA(g - j).equals(this.lettreA(g))) ff.enfiler(new Integer(g - j)); } while (ff.getLongueur() <= k && g < j + m - 1); if (ff.getLongueur() <= k) v.addElement(new Integer(j)); } } return v; } private File inegFusion(int f, int j, int g, File ff, File fg, Mot x, int k) { File fj = new File(); while (fj.getLongueur() <= k && ff.getLongueur() > 0 && fg.getLongueur() > 0) { int p = ((Integer)ff.tete()).intValue(); int q = ((Integer)fg.tete()).intValue(); if (p < q) { ff.defiler(); fj.enfiler(new Integer(p - j + f)); } else if (q < p) { fg.defiler(); fj.enfiler(new Integer(q - j + f)); } else { ff.defiler(); fg.defiler(); if (x.lettreA(p - j + f).equals(this.lettreA(f + p))) fj.enfiler(new Integer(p - j + f)); } } while (fj.getLongueur() <= k && ff.getLongueur() > 0) { int p = ((Integer)ff.defilement()).intValue(); fj.enfiler(new Integer(p - j + f)); } while (fj.getLongueur() <= k && fg.getLongueur() > 0 && ((Integer)fg.tete()).intValue() <= g - f) { int q = ((Integer)fg.defilement()).intValue(); fj.enfiler(new Integer(q - j + f)); } return fj; } public File[] preLInegalites(int k) { int i, m = this.getLongueur(); File[] fg = new File[m]; for (int q = 1; q <= m - 1; ++q) { fg[q] = new File(); i = q; while (fg[q].getLongueur() < 2*k + 1 && q < i) { if (!this.lettreA(i).equals(this.lettreA(i - q))) fg[q].enfiler(new Integer(i)); ++i; } } return fg; } public Vector lMotifCourt(Mot x, Alphabet alphabet) { Lettre a; Enumeration e = alphabet.elements(); int m = x.getLongueur(), masq, n = this.getLongueur(), r; int[] s = new int[alphabet.getCard()]; Vector v = new Vector(); while (e.hasMoreElements()) { a = (Lettre)e.nextElement(); s[alphabet.rang(a)] = ~0; } masq = 1; for (int i = 0; i <= m - 1; ++i) { s[alphabet.rang(this.lettreA(i))] &= masq; masq <<= 1; } masq >>= 1; r = ~0; for (int j = 0; j <= n - 1; ++j) { r = (r << 1) | s[alphabet.rang(this.lettreA(j))]; if ((r & masq) == 0) v.addElement(new Integer(j)); } return v; } public Vector lInegMotifCourt(Mot x, int k, Alphabet alphabet) { Lettre a; Enumeration e = alphabet.elements(); int m = x.getLongueur(), masq, n = this.getLongueur(), t, tp; int[] r = new int[k + 1], s = new int[alphabet.getCard()]; Vector v = new Vector(); while (e.hasMoreElements()) { a = (Lettre)e.nextElement(); s[alphabet.rang(a)] = ~0; } masq = 1; for (int i = 0; i <= m - 1; ++i) { s[alphabet.rang(this.lettreA(i))] &= masq; masq <<= 1; } masq >>= 1; r[0] = ~0; for (int ell = 1; ell <= k; ++ell) r[ell] = r[ell - 1] << 1; for (int j = 0; j <= n - 1; ++j) { t = r[0]; r[0] = (r[0] << 1) | s[alphabet.rang(this.lettreA(j))]; for (int ell = 1; ell <= k; ++ell) { tp = r[ell]; r[ell] = ((r[ell] << 1) | s[alphabet.rang(this.lettreA(j))]) & (t << 1); t = tp; } if ((r[k] & masq) == 0) v.addElement(new Integer(j)); } return v; } public Vector lDiffMotifCourt(Mot x, int k, Alphabet alphabet) { Lettre a; Enumeration e = alphabet.elements(); int m = x.getLongueur(), masq, n = this.getLongueur(), t, tp; int[] r = new int[k + 1], s = new int[alphabet.getCard()]; Vector v = new Vector(); while (e.hasMoreElements()) { a = (Lettre)e.nextElement(); s[alphabet.rang(a)] = ~0; } masq = 1; for (int i = 0; i <= m - 1; ++i) { s[alphabet.rang(this.lettreA(i))] &= masq; masq <<= 1; } masq >>= 1; r[0] = ~0; for (int ell = 1; ell <= k; ++ell) r[ell] = r[ell - 1] << 1; for (int j = 0; j <= n - 1; ++j) { t = r[0]; r[0] = (r[0] << 1) | s[alphabet.rang(this.lettreA(j))]; for (int ell = 1; ell <= k; ++ell) { tp = r[ell]; r[ell] = ((r[ell] << 1) | s[alphabet.rang(this.lettreA(j))]) & ((t & r[ell - 1]) << 1) & t; t = tp; } if ((r[k] & masq) == 0) v.addElement(new Integer(j)); } return v; } }