Java中Levenshtein算法的问题

Java中Levenshtein算法的问题,java,string,algorithm,Java,String,Algorithm,我想将用于以下任务:如果我网站上的用户搜索某个值(他在输入中输入字符),我想立即使用AJAX检查建议,就像Google Instant一样 我觉得Levenshtein算法对于这样的任务来说太慢了。为了检查它的行为,我首先用Java实现了它,在方法的每次递归调用中打印出两个字符串 public class Levenshtein { public static void main(String[] arg){ String a = "Hallo Zusammen";

我想将用于以下任务:如果我网站上的用户搜索某个值(他在输入中输入字符),我想立即使用AJAX检查建议,就像Google Instant一样

我觉得Levenshtein算法对于这样的任务来说太慢了。为了检查它的行为,我首先用Java实现了它,在方法的每次递归调用中打印出两个
字符串

public class Levenshtein {
    public static void main(String[] arg){
        String a = "Hallo Zusammen";
        String b = "jfdss Zusammen";

        int res = levenshtein(a, b);

        System.out.println(res);
    }

    public static int levenshtein(String s, String t){
        int len_s = s.length();
        int len_t = t.length();
        int cost = 0;

        System.out.println("s: " + s + ", t: " + t);

        if(len_s>0 && len_t>0){
            if(s.charAt(0) != t.charAt(0)) cost = 1;
        }

        if(len_s == 0){
            return len_t;
        }else{
            if(len_t == 0){
                return len_s;
            }else{
                String news = s.substring(0, s.length()-1);
                String newt = t.substring(0, t.length()-1);
                return min(levenshtein(news, t) + 1,
                            levenshtein(s, newt) + 1,
                            levenshtein(news, newt) + cost);
            }
        }
    }

    public static int min(int a, int b, int c) {
          return Math.min(Math.min(a, b), c);
    }
}
然而,这里有几点:

  • 检查
    if(len\u s>0&&len\u t>0)
    是我添加的,因为我得到了一个带有上述测试值的
    StringIndexOutOfBoundsException
  • 使用上述测试值,该算法似乎可以无限计算
是否可以对算法进行优化以使其适合我,还是应该使用完全不同的算法来完成所需的任务?

1)关于Levenshtein距离算法改进的几句话

Levenshteins距离的递归实现具有指数复杂性

我建议您使用记忆技术,实现Levenshtein距离而不使用递归,并将复杂性降低到
O(N^2)
(需要
O(N^2)
内存)

2) 关于自动完成的几句话

Levenshtein的距离只有在您需要找到精确匹配时才适用。

但是如果你的关键词是苹果,而用户输入的是绿苹果,那该怎么办呢?查询和关键字之间的Levenshteins距离将很大(7点)。苹果和bcdfghk(哑字符串)之间的Levenstein距离也将是7点!

我建议您使用全文搜索引擎(例如)。诀窍是-您必须使用模型来表示每个关键字。

简言之:
1)您必须将每个关键字表示为文档,其中包含n个字符:
apple->[ap,pp,pl,le]


2)将每个关键字转换为一组n-gram后-您必须在搜索引擎中按n-gram为每个关键字文档编制索引。您必须创建如下索引:

...
ap -> apple, map, happy ...
pp -> apple ...
pl -> apple, place ...
...
3)所以你有n克指数当您得到查询时,您必须将其拆分为n-gram。在此之后,您将有一组用户查询n-grams。你所需要的就是匹配搜索引擎中最相似的文档。在草案方法中,这就足够了。

4)为了获得更好的建议,您可以根据Levenshtein距离对搜索引擎的结果进行排名。

p.S.我建议您通读这本书

导入java.util.Scanner;
import java.util.Scanner;

public class Algorithmm {
    public static void main(String args[])
    {
        Scanner sc= new Scanner(System.in);
        System.out.println("Enter the correct string ");
        String correct=sc.nextLine();
        System.out.println("Enter the incorrect string ");
        String incorrect=sc.nextLine();
        int i=correct.length(),j=incorrect.length();
        ++i ; ++j;
        int a[][] = new int[i][j];
        int b[] = new int[3];       
        for(int m=0;m<i;m++)
            for(int n=0;n<j;n++)
            {

                        if(m==0 || n==0)
                        {
                          a[0][n]=n;
                          a[m][0]=m;
                        }
                        else
                        {
                            b[0]=a[m-1][n-1]; b[1]=a[m-1][n]; b[2]=a[m][n-1];


                            if ( correct.charAt(m-1) == incorrect.charAt(n-1)  )
                            {
                                a[m][n]=a[m-1][n-1];
                            }

                            else
                            {
                                for(int t=0;t<2;t++)
                                    for(int u=0;u<2-t;u++)
                                        if(b[u]>b[u+1])
                                            b[u]=b[u+1];


                                a[m][n]=b[0]+1;


                            }

                        }

            }


        for(int m=0;m<i;m++)
        {
            for(int n=0;n<j;n++)
                System.out.print( a[m][n] +"  ");  
            System.out.print("\n");                
        }



        System.out.println(" Levenshtein distance :  "+a[i-1][j-1]);

    }

}
公共类算法{ 公共静态void main(字符串参数[]) { 扫描仪sc=新的扫描仪(System.in); System.out.println(“输入正确的字符串”); 字符串正确=sc.nextLine(); System.out.println(“输入不正确的字符串”); 字符串不正确=sc.nextLine(); int i=正确的.length(),j=不正确的.length(); ++i;++j; int a[][]=新int[i][j]; int b[]=新int[3]; 对于(int m=0;m
公共类算法){
公共静态void main(字符串参数[])
{
扫描仪sc=新的扫描仪(System.in);
System.out.println(“输入正确的字符串”);
字符串正确=sc.nextLine();
System.out.println(“输入不正确的字符串”);
字符串不正确=sc.nextLine();
int i=正确的.length(),j=不正确的.length();
++i;++j;
int a[][]=新int[i][j];
int b[]=新int[3];

对于(int m=0;m有一个开源库,java util(),它有一个StringUtilities.LevenshteInstance(string1,string2)API,它以O(N^2)的复杂度实现,并且只使用与O(N)成比例的内存[如上所述]

该库还包括damerauLevenshteinDisance()。Damerau Levenshtein将字符换位(swap)计算为一次编辑,而适当的Levenshtein将其计算为两次编辑。Damerau Levenshtein的缺点是它不像原始Levenshtein那样具有三角形相等

三角平等的伟大描绘:

您可以使用:

查找两个字符串之间的Levenshtein距离

这是将一个字符串更改为所需的更改数 另一种情况是,每次更改都是单个字符的修改 (删除、插入或替换)

Levenshtein距离算法的先前实现是 从

Chas Emerick用Java编写了一个实现,避免了 OutOfMemoryError,在使用Java实现时可能发生此错误 用非常大的弦

Levenshtein距离算法的这个实现来自

...
ap -> apple, map, happy ...
pp -> apple ...
pl -> apple, place ...
...
import java.util.Scanner;

public class Algorithmm {
    public static void main(String args[])
    {
        Scanner sc= new Scanner(System.in);
        System.out.println("Enter the correct string ");
        String correct=sc.nextLine();
        System.out.println("Enter the incorrect string ");
        String incorrect=sc.nextLine();
        int i=correct.length(),j=incorrect.length();
        ++i ; ++j;
        int a[][] = new int[i][j];
        int b[] = new int[3];       
        for(int m=0;m<i;m++)
            for(int n=0;n<j;n++)
            {

                        if(m==0 || n==0)
                        {
                          a[0][n]=n;
                          a[m][0]=m;
                        }
                        else
                        {
                            b[0]=a[m-1][n-1]; b[1]=a[m-1][n]; b[2]=a[m][n-1];


                            if ( correct.charAt(m-1) == incorrect.charAt(n-1)  )
                            {
                                a[m][n]=a[m-1][n-1];
                            }

                            else
                            {
                                for(int t=0;t<2;t++)
                                    for(int u=0;u<2-t;u++)
                                        if(b[u]>b[u+1])
                                            b[u]=b[u+1];


                                a[m][n]=b[0]+1;


                            }

                        }

            }


        for(int m=0;m<i;m++)
        {
            for(int n=0;n<j;n++)
                System.out.print( a[m][n] +"  ");  
            System.out.print("\n");                
        }



        System.out.println(" Levenshtein distance :  "+a[i-1][j-1]);

    }

}
public class Algorithmm {
    public static void main(String args[])
    {
        Scanner sc= new Scanner(System.in);
        System.out.println("Enter the correct string ");
        String correct=sc.nextLine();
        System.out.println("Enter the incorrect string ");
        String incorrect=sc.nextLine();
        int i=correct.length(),j=incorrect.length();
        ++i ; ++j;
        int a[][] = new int[i][j];
        int b[] = new int[3];       
        for(int m=0;m<i;m++)
            for(int n=0;n<j;n++)
            {               
                        if(m==0 || n==0)
                        {
                           a[0][n]=n;
                           a[m][0]=m;
                        }
                        else
                        {
                            b[0]=a[m-1][n-1]; b[1]=a[m-1][n]; b[2]=a[m][n-1];    
                            if ( correct.charAt(m-1) == incorrect.charAt(n-1)  )                        
                                a[m][n]=a[m-1][n-1];                                                        
                            else
                            {
                       //instead of using the above code for finding the smallest number in       the array 'b' we can simplyfy that code to the following, so that we can reduce the execution time.//

                                if(  (b[0]<=b[1]) && (b[0])<=b[2]  )
                                    a[m][n]=b[0]+1;
                                else if(  (b[1]<=b[0]) && (b[1])<=b[2]  )
                                    a[m][n]=b[1]+1;
                                else
                                    a[m][n]=b[2]+1;    
                            }                            
                        }                
            }               
        for(int m=0;m<i;m++)
        {
            for(int n=0;n<j;n++)
                System.out.print( a[m][n] +"  ");  
            System.out.print("\n");                
        }       
        System.out.println("
Levenshtein distance :
  "+a[i-1][j-1]);        
    }
}
 StringUtils.getLevenshteinDistance(null, *)             = IllegalArgumentException
 StringUtils.getLevenshteinDistance(*, null)             = IllegalArgumentException
 StringUtils.getLevenshteinDistance("","")               = 0
 StringUtils.getLevenshteinDistance("","a")              = 1
 StringUtils.getLevenshteinDistance("aaapppp", "")       = 7
 StringUtils.getLevenshteinDistance("frog", "fog")       = 1
 StringUtils.getLevenshteinDistance("fly", "ant")        = 3
 StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
 StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
 StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
 StringUtils.getLevenshteinDistance("hello", "hallo")    = 1