2011-05-07 10 views
10

Kullanıcı girişi alacağı, bu dizeyi belirteçlere bölen ve daha sonra söz dizisindeki sözcükler için bir sözlük arayacak bir program uygulamaya çalışıyorum. Ayrıştırılmış dizge için hedefim, her bir jetonun İngilizce bir kelime olması. Örnek içinJava Sözlük Arayıcı

:

Input: 
     aman 

Split Method: 
     a man 
     a m an 
     a m a n 
     am an 
     am a n 
     ama n 

Desired Output: 
     a man 

Şu anda istenen çıkış parçası kadar her şeyi yapar bu kodu vardır: Böyle bir şekilde sözlüğü (depolamak için daha iyi yollar var biliyorum

import java.util.Scanner; 
import java.io.*; 

public class Words { 

    public static String[] dic = new String[80368]; 

    public static void split(String head, String in) { 

     // head + " " + in is a segmentation 
     String segment = head + " " + in; 

     // count number of dictionary words 
     int count = 0; 
     Scanner phraseScan = new Scanner(segment); 
     while (phraseScan.hasNext()) { 
      String word = phraseScan.next(); 
      for (int i=0; i<dic.length; i++) { 
       if (word.equalsIgnoreCase(dic[i])) count++; 
      } 
     } 

     System.out.println(segment + "\t" + count + " English words"); 

     // recursive calls 
     for (int i=1; i<in.length(); i++) { 
      split(head+" "+in.substring(0,i), in.substring(i,in.length())); 
     } 
    } 

    public static void main (String[] args) throws IOException { 
     Scanner scan = new Scanner(System.in); 
     System.out.print("Enter a string: "); 
     String input = scan.next(); 
     System.out.println(); 

     Scanner filescan = new Scanner(new File("src:\\dictionary.txt")); 
     int wc = 0; 
     while (filescan.hasNext()) { 
      dic[wc] = filescan.nextLine(); 
      wc++; 
     } 

     System.out.println(wc + " words stored"); 

     split("", input); 

    } 
} 

ikili arama ağacı veya bir karma tablosu), ancak bunları nasıl uygulayacağımı bilmiyorum.

Her segmentin sözlükte bir sözcük olup olmadığını görmek için bölünmüş dizeyi kontrol eden bir yöntemin nasıl uygulanacağına takılıyorum.

Herhangi bir yardım çok iyi olurdu, cevabım aptalca görünüyor Eğer gerçekten yakın ve ben Zorlandığınız olduğun yerde emin değilim, çünkü bu kadar size

+0

olası yinelenen [Word'de Sözlüğü mı yoksa değil] (http://stackoverflow.com/questions/5918838/word-is-in-dictionary -veya değil) –

+0

Beklediğiniz en büyük giriş dizesi hangisi? –

+0

Her hangi bir uzunlukta olabilir, ama muhtemelen 20 karakterden daha uzun olmasını beklemiyorum muhtemelen 50 MAX – Brendan

cevap

14

20 veya daha fazla karakteri desteklemek istiyorsanız, giriş dizesini mümkün olan her şekilde bölmek, makul bir süre içinde bitmeyecektir. İşte daha verimli bir yaklaşım, yorum inline:

public static void main(String[] args) throws IOException { 
    // load the dictionary into a set for fast lookups 
    Set<String> dictionary = new HashSet<String>(); 
    Scanner filescan = new Scanner(new File("dictionary.txt")); 
    while (filescan.hasNext()) { 
     dictionary.add(filescan.nextLine().toLowerCase()); 
    } 

    // scan for input 
    Scanner scan = new Scanner(System.in); 
    System.out.print("Enter a string: "); 
    String input = scan.next().toLowerCase(); 
    System.out.println(); 

    // place to store list of results, each result is a list of strings 
    List<List<String>> results = new ArrayList<List<String>>(); 

    long time = System.currentTimeMillis(); 

    // start the search, pass empty stack to represent words found so far 
    search(input, dictionary, new Stack<String>(), results); 

    time = System.currentTimeMillis() - time; 

    // list the results found 
    for (List<String> result : results) { 
     for (String word : result) { 
      System.out.print(word + " "); 
     } 
     System.out.println("(" + result.size() + " words)"); 
    } 
    System.out.println(); 
    System.out.println("Took " + time + "ms"); 
} 

public static void search(String input, Set<String> dictionary, 
     Stack<String> words, List<List<String>> results) { 

    for (int i = 0; i < input.length(); i++) { 
     // take the first i characters of the input and see if it is a word 
     String substring = input.substring(0, i + 1); 

     if (dictionary.contains(substring)) { 
      // the beginning of the input matches a word, store on stack 
      words.push(substring); 

      if (i == input.length() - 1) { 
       // there's no input left, copy the words stack to results 
       results.add(new ArrayList<String>(words)); 
      } else { 
       // there's more input left, search the remaining part 
       search(input.substring(i + 1), dictionary, words, results); 
      } 

      // pop the matched word back off so we can move onto the next i 
      words.pop(); 
     } 
    } 
} 

Örnek çıktı: İşte

Enter a string: aman 

a man (2 words) 
am an (2 words) 

Took 0ms 

çok daha uzun giriş var:

Enter a string: thequickbrownfoxjumpedoverthelazydog 

the quick brown fox jump ed over the lazy dog (10 words) 
the quick brown fox jump ed overt he lazy dog (10 words) 
the quick brown fox jumped over the lazy dog (9 words) 
the quick brown fox jumped overt he lazy dog (9 words) 

Took 1ms 
+0

diyelim. ** Başka bir deyişle kelimeleri veritabanında saklamak **.Bu, çok sayıda kelime ile çalışırken (> 4 milyon) performansı artıracaktır. –

+0

@jmendeth: emin olun, bir sözlük yeterli büyüklükte ve yeterli bellek mevcut değilse yardımcı olabilir. Çoğu sözlükler o kadar geniş değil. Test ettiğim daha büyük olan 400.000'den fazla kelimeye sahip ve 38MB'a ihtiyaç duyuyor. Sözlüğünün 80k kelimesi olduğu ve sadece 7MB civarında olduğu için OP'nin bir veritabanına ihtiyacı yoktur. Çok sayıda kelime için muhtemelen bir veritabanına gitmeden önce bir trie gibi farklı bir veri yapısı kullanmayı deneyeceğim. Bir veritabanı iyi çalışıyor olsa da, verdiğim 36 karakter örnek girişinde sadece 335 arama var. – WhiteFang34

+0

Haklısınız, ancak bazen (bu durumda değil) diğer diller/sözlüklerin sözlükleri yaklaşık 10 Milyon kelime olabilir. –

0

ederiz.

basit yolu (kod yukarıdaki basitçe daha iyi olabilir bir karma-tablo olarak bu uygulama eşleştirilmiş bir deyişle

int count = 0; int total = 0; 
    Scanner phraseScan = new Scanner(segment); 
    while (phraseScan.hasNext()) { 
     total++ 
     String word = phraseScan.next(); 
     for (int i=0; i<dic.length; i++) { 
      if (word.equalsIgnoreCase(dic[i])) count++; 
     } 
    } 
    if(total==count) System.out.println(segment); 

sayısının o kelimelerin sayısı için bir sayaç eklemek ve karşılaştırmak için olurdu verilen daha hızlı, kesinlikle) ve gerçekten kolay olurdu.

HashSet<String> dict = new HashSet<String>() 
dict.add("foo")// add your data 


int count = 0; int total = 0; 
Scanner phraseScan = new Scanner(segment); 
while (phraseScan.hasNext()) { 
    total++ 
    String word = phraseScan.next(); 
    if(dict.contains(word)) count++; 
} 

Bunu yapmak için başka daha iyi yollar vardır. Biri, arama için biraz daha yavaş olan, ancak verileri daha verimli bir şekilde saklayan bir trie (http://en.wikipedia.org/wiki/Trie). Büyük bir sözlüğünüz varsa, belleğe sığdıramayabilirsiniz, bu nedenle bir veritabanı veya bir BDB (http://en.wikipedia.org/wiki/Berkeley_DB)

0

paket LinkedList;

import java.util.LinkedHashSet;

public class dictionaryCheck {

private static LinkedHashSet<String> set; 
private static int start = 0; 
private static boolean flag; 

public boolean checkDictionary(String str, int length) { 

    if (start >= length) { 
     return flag; 
    } else { 
     flag = false; 
     for (String word : set) { 

      int wordLen = word.length(); 

      if (start + wordLen <= length) { 

       if (word.equals(str.substring(start, wordLen + start))) { 
        start = wordLen + start; 
        flag = true; 
        checkDictionary(str, length); 

       } 
      } 
     } 

    } 

    return flag; 
} 

public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    set = new LinkedHashSet<String>(); 
    set.add("Jose"); 
    set.add("Nithin"); 
    set.add("Joy"); 
    set.add("Justine"); 
    set.add("Jomin"); 
    set.add("Thomas"); 
    String str = "JoyJustine"; 
    int length = str.length(); 
    boolean c; 

    dictionaryCheck obj = new dictionaryCheck(); 
    c = obj.checkDictionary(str, length); 
    if (c) { 
     System.out 
       .println("String can be found out from those words in the Dictionary"); 
    } else { 
     System.out.println("Not Possible"); 
    } 

} 

} arasında

+0

Basit ve Etkin Çözüm. Bir şeyi özlediysem haber ver. Zaman karmaşıklığı üstelik sanırım. Polinom zaman karmaşıklığı, Dinamik Programlama Çözümü kullanılarak sağlanabilir. –

+0

Bu kod OP'nin problemini çözebilirken, kodun ne yaptığını veya nasıl yaptığını açıklamalıdır. _Just Code_ cevapları üzerine kaşlarını çattı. – BrokenBinary