Created
March 16, 2013 11:55
-
-
Save khajavi/5176087 to your computer and use it in GitHub Desktop.
Spell Corrector
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.*; | |
import java.util.*; | |
import java.util.regex.*; | |
class Spelling { | |
// برای اینکه سرعت الگوریتم تصحیحکنندهٔ املایی بالا رود نیاز به جستوجو با سرعت بالا در یک بانک اطلاعاتی وسیعی داریم. به همین دلیل از جدول هش استفاده میکنیم: | |
private final HashMap<String, Integer> nWords = new HashMap<String, Integer>(); | |
// کلاس Spelling یک ساختمان دادهٔ جدید برای جمعآوری لغات آماده میکند. | |
public Spelling(String file) throws IOException { | |
BufferedReader in = new BufferedReader(new FileReader(file)); // ساخت بافر ورودی جهت دریافت دادههای خام اطلاعاتی | |
Pattern p = Pattern.compile("\\w+"); // ایجاد پترن جدید برای شناسایی کلمات املایی | |
// حلقهٔ for زیر شروع پارس کردن فایل ورودی میکند و کلمه به کلمه اطلاعات را از ورودی دریافت کرده و با پترن مشخص شده مطابقت میدهد و در صورت تطبیق با عبارت منظم آن را درود ساختمان دادهٔ جدول هش میکند. | |
for (String temp = ""; temp != null; temp = in.readLine()) { | |
Matcher m = p.matcher(temp.toLowerCase()); | |
while (m.find()) { | |
nWords.put((m.group()), nWords.containsKey(m.group()) ? nWords.get(m.group()) + 1 : 1); // کلمات تطبیق یافته با عبارت منظم را وارد جدول هش کن و برای آن کلید مخصوص قرار ده | |
} | |
} | |
in.close(); // فایل ورودی را ببند. | |
} | |
// تابع edit کلمهٔ ورودی را از کاربر دریافت کرده و ۴ الگوریتم متفاوت روی آن اجرا میکند | |
private final ArrayList<String> edits(String word) { | |
ArrayList<String> result = new ArrayList<String>(); | |
// الگوریتم اول: Deletion. این الگوریتم به این احتمال میپردازد که کاربر در هنگام حروفچینی کلمه، یک کاراکتر اضافه تایپ کرده است. پس به این مناسبت تمام احتمالات مورد نظر را در آرایهٔ متغییر result ذخیره میکند. | |
for (int i = 0; i < word.length(); ++i) { //Deletion | |
result.add(word.substring(0, i) + word.substring(i + 1)); | |
} | |
// الگوریتم دوم:Transpositions. این الگوریتم به این احتمال میپردازد که کاربر در هنگام حروفچینی کلمه، دو کاراکتر متوالی را اشتباها جابهجا تایپ کرده است. به این مناسبت تمام احتمالات مورد نظر را به آرايهٔ result اضافه میکند. | |
for (int i = 0; i < word.length() - 1; ++i) { //transpositions | |
result.add(word.substring(0, i) + word.substring(i + 1, i + 2) + word.substring(i, i + 1) + word.substring(i + 2)); | |
} | |
// الگوریتم سوم: Alteration. این الگوریتم به این احتمال میپردازد که کاربر در هنگام حروفچینی کلمه، یکی از حروف را اشتباه تایپ کرده است. به این مناسب تمام احتمالات مورد نظر را به آرایهٔ result اضافه میکند. | |
for (int i = 0; i < word.length(); ++i) { | |
for (char c = 'a'; c <= 'z'; ++c) { //alterations | |
result.add(word.substring(0, i) + String.valueOf(c) + word.substring(i + 1)); | |
} | |
} | |
// الگوریتم چهارم: Insertation. این الگوریتم به این احتمال میپردازد که کاربر در هنگام حروفچینی کلمه، یک حرف از کلمه را جا انداخته و تایپ نکرده. به این مناسبت تمام احتمالات مورد نظر را به آرايهٔ result اضافه میکند. | |
for (int i = 0; i <= word.length(); ++i) { //insertions | |
for (char c = 'a'; c <= 'z'; ++c) { | |
result.add(word.substring(0, i) + String.valueOf(c) + word.substring(i)); | |
} | |
} | |
return result; //در پایان مجموعه احتمالات جدید از کلمات داریم. | |
} | |
public final String correct(String word) { // این تابع سعی میکند املای صحیح واژهٔ داده شده را با توجه به احتمالات محاسبه شده پیدا کند. | |
// اگر واژه صحیح تایپ شده باشد توسط حلقهٔ زیر قابل تشخیص است. | |
if (nWords.containsKey(word)) { | |
return word; | |
} | |
ArrayList<String> list = edits(word); //new array list (new candidate words) | |
HashMap<Integer, String> candidates = new HashMap<Integer, String>(); | |
// حلقهٔ زیر از بین احتمالات به دست آمده در مرحلهٔ قبل، جستوجو میکند تا واژهای صحیح پیدا کند و آن را در متغیر کاندید قرار میدهد. | |
for (String s : list) { | |
if (nWords.containsKey(s)) { | |
candidates.put(nWords.get(s), s); | |
} | |
} | |
// ممکن است واژهٔ صحیح برای یک کلمه کاندید شوند. قسمت زیر تنها یکی از این واژهها را بر میگزیند. | |
if (candidates.size() > 0) { | |
return candidates.get(Collections.max(candidates.keySet())); | |
} | |
// در زیر تمام مراحل گفته شده را دوباره تکرار می کند و در این صورت ممکن است واژههایی که کاربر ۴ احتمال ممکنه را به صورت تلقیقی اشتباه تایپ کرده باشد پیدا کند. برای مثال کاربر هم یک واژه کم نوشته باشد و هم دو واژه را جابهجا نوشته باشد. | |
for (String s : list) { | |
for (String w : edits(s)) { | |
if (nWords.containsKey(w)) { | |
candidates.put(nWords.get(w), w); | |
} | |
} | |
} | |
return candidates.size() > 0 ? candidates.get(Collections.max(candidates.keySet())) : word; | |
} | |
// تابع زیر نیز درصد خطای واژهٔ داده شده را محاسبه میکند. | |
public final void approximateError(String word, String result) { | |
if (word.compareTo(result) == 0) { | |
System.out.println("The approximate of Error: " + "0%"); | |
} else if (word.length() == result.length()) { | |
float count = 0; | |
for (int i = 0; i < word.length(); i++) { | |
if (word.toCharArray()[i] != result.toCharArray()[i]) { | |
count++; | |
} | |
} | |
System.out.println("The approximate of Error: " + (count/ word.length()) * 100 + "%"); | |
} | |
} | |
// تابع اصلی: | |
public static void main(String args[]) throws IOException { | |
if (args.length > 0) { | |
Spelling sp = new Spelling("big.txt"); | |
System.out.println(sp.correct(args[0])); | |
sp.approximateError(args[0], sp.correct(args[0])); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment