Skip to content

Instantly share code, notes, and snippets.

@khajavi
Created March 16, 2013 11:55
Show Gist options
  • Save khajavi/5176087 to your computer and use it in GitHub Desktop.
Save khajavi/5176087 to your computer and use it in GitHub Desktop.
Spell Corrector
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