/* * Lisans bilgisi icin lutfen proje ana dizinindeki zemberek2-lisans.txt dosyasini okuyunuz. */ package net.zemberek.araclar; /** * Genel metin araçları. String benzerliği, Q klavye mesafesi gibi fonksiyonları barındırır. * @author MDA */ public class MetinAraclari { private static JaroWinkler jaroWinkler = new JaroWinkler(); /** * Degistirilmis Levenshtein Edit Dist. algoritması. transpozisyonları da 1 düzeltme mesafesi * olarak hesaplar. * TODO: Alphan'ın mesafe aşımını sezip kısa kesme kodunu ekle. * @param s kaynak * @param t hedef * @param limit sinir degeri * @return iki kelime arasindaki mesafe, tamsayi cinsinden. kucuk rakamlar daha buyuk benzerligi gosterir. */ private static int duzeltmeMesafesi(String s, String t, int limit) { int n = s.length(); //length of s int m = t.length(); //length of t int[][] d = new int[n + 1][m + 1]; // matrix int cost; // cost // Step 1 if (n == 0) return m; if (m == 0) return n; // Step 2 for (int i = 0; i <= n; d[i][0] = i++) ; for (int j = 0; j <= m; d[0][j] = j++) ; // Step 3 for (int i = 1; i <= n; i++) { //Step 4 for (int j = 1; j <= m; j++) { // Step 5 cost = (t.charAt(j-1) == s.charAt(i-1) ? 0 : 1); // Step 6 d[i][j] = Math.min(Math.min(d[i-1][j] + 1, d[i][j-1] + 1), d[i-1][j-1] + cost); // Step 6A if (i > 1 && j > 1) { int trans = d[i-2][j-2] + 1; if (s.charAt(i-2) != t.charAt(j-1)) trans++; if (s.charAt(i-1) != t.charAt(j-2)) trans++; if (d[i][j] > trans) d[i][j] = trans; } } } // Step 7 return d[n][m] > limit ? limit + 1 : d[n][m]; } public static boolean duzeltmeMesafesiIcinde(String source, String target, int dist) { return (duzeltmeMesafesi(source, target, dist) <= dist); } /** * Verilen s1 stringinin verilen distance düzeltme mesafesi çerçevesinde * s2 stringinin alt stringi olup olmadığını döndürürr. Örneğin: *
   * isInSubStringLevenshteinDistance("elma","ekmalar",1) -> true
   * isInSubStringLevenshteinDistance("elma","emalar",1) -> true
   * isInSubStringLevenshteinDistance("elma","eksalar",1) -> false (substring min dist=2)
   * 
* * @param s1 : * @param s2 : s1'i distance düzeltme mesafesi içinde kapsayıp kapsamadığı araştırılan String * @param distance : düzeltme mesafesi * @return eger istenilen mesafede is true. */ public static boolean parcasiDuzeltmeMesafesiIcinde(String s1, String s2, int distance) { if (s2.length() < (s1.length() - distance)) return false; if (s2.length() >= s1.length()) { String test = s2.substring(0, s1.length()); if (duzeltmeMesafesiIcinde(s1, test, distance)) return true; test = s2.substring(0, s1.length() - 1); if (duzeltmeMesafesiIcinde(s1, test, distance)) return true; if (s2.length() >= s1.length() + 1) { test = s2.substring(0, s1.length() + 1); if (duzeltmeMesafesiIcinde(s1, test, distance)) return true; } } else { if (duzeltmeMesafesiIcinde(s1, s2, distance)) return true; } return false; } public static int duzeltmeMesafesi(String source, String target) { int maxDif = Math.max(source.length(), target.length()); return duzeltmeMesafesi(source, target, maxDif); } /** * s1 ile s2'nin benzerlik oranini hesaplar. * * @param s1 * @param s2 * @return 0-1.0 arasi bir deger. Buyuk rakamlar kelimelerin daha benzer oldugunu gosterir. */ public static double sozcukBenzerlikOrani(String s1, String s2) { return jaroWinkler.benzerlikOrani(s1, s2); } /** * s1 ile s2'nin enazBenzerlik degeri kadar ya da daha benzer olup olmadigini test eder. * * @param s1 * @param s2 * @param enazBenzerlik * @return eger benzerlik orani enazBenzerlik'na es ya da buyukse true */ public static boolean sozcukBenzerlikTesti(String s1, String s2, double enazBenzerlik) { return (jaroWinkler.benzerlikOrani(s1, s2) >= enazBenzerlik); } }