Wagner Fischer算法+显示步骤

时间:2017-01-02 20:00:40

标签: java algorithm

我在java中用输入成本实现了Wagner Fischer算法,但我想显示所有步骤。 我搜索但无法找到任何想法。很长一段时间后,我试图将每个转换保持在矩阵中并与成本一起回到第一个解决方案然后反转它...这是一个好主意,如果是的话,我该如何设定条件?



kitten -> sitting
1.replace k with s
2.keep i
3.keep t
4.keep t
5.replace t
6.add g




我尝试为显示步骤制作功能,但无法弄清楚如何解决它。

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Principal {
    static int c1, c2, c3;
    static String word1, word2;

    public  static void main(String[] args) throws FileNotFoundException {
        Scanner data_in = new Scanner(new File("data.in"));
        word1 = data_in.next();
        word2 = data_in.next();
        c1 = data_in.nextInt();
        c2 = data_in.nextInt();
        c3 = data_in.nextInt();

        System.out.printf("\nInsert: %s, Delete: %s, Replace: %s\n", c1, c2, c3);

        System.out.printf("\nLevenstheinDistance: %s", LevenshteinDistance(word1, word2, c1, c2, c3));
    }

    private static int LevenshteinDistance(String str1, String str2, int InsCost, int DelCost, int ReplCost)
    {
        if(word1.length() == 0)
            return InsCost*str1.length();
        if(word2.length() == 0)
            return DelCost*str2.length();

        int substitutionCost = ReplCost;
        if(ReplCost > InsCost + DelCost)
            ReplCost = InsCost + DelCost;

        Solution[][] ManageSol = new Solution[str1.length()+1][str2.length()+1];

        for(int i = 0; i <= str1.length(); i++)
        {
            for(int j = 0; j <= str2.length(); j++){
                ManageSol[i][j] = new Solution();
            }
        }

        System.out.printf("\nLungime str1: %s", str1.length());
        System.out.printf("\nLungime str2: %s", str2.length());

        for(int i = 0; i <= str1.length(); i++)
        {
            for (int j = 0; j <= str2.length(); j++)
            {
                if (i == 0)
                    ManageSol[i][j].solution = j;
                else if (j == 0)
                    ManageSol[i][j].solution = i;
                else if (str1.charAt(i - 1) == str2.charAt(j - 1))
                {
                    substitutionCost = 0;
                    ManageSol[i][j].ecqualTo(minimum(
                            ManageSol[i][j - 1].solution + InsCost,
                            ManageSol[i - 1][j].solution + DelCost,
                            ManageSol[i - 1][j - 1].solution + substitutionCost));
                    System.out.printf("\nManagerSol[%s, %s]: ch1: %s, ch2: %s", i, j, str1.charAt(i - 1), str2.charAt(j - 1));
                }
                else
                {
                    substitutionCost = 1;
                    ManageSol[i][j].ecqualTo(minimum(
                            ManageSol[i][j - 1].solution + InsCost,
                            ManageSol[i - 1][j].solution + DelCost,
                            ManageSol[i - 1][j - 1].solution + substitutionCost));
                    System.out.printf("\nManagerSol[%s, %s]: ch1: %s, ch2: %s", i, j, str1.charAt(i - 1), str2.charAt(j - 1));
                }
            }
        }

        System.out.printf("\n");
        path(ManageSol, str1.length(), str2.length(), str1, str2);
        System.out.printf("\n");

        for(int i = 0; i <= str1.length(); i++)
        {
            for (int j = 0; j <= str2.length(); j++)
            {
                System.out.printf("[%s,%s]:(%s,%s) ", i, j, ManageSol[i][j].solution, ManageSol[i][j].operation);
            }
            System.out.printf("\n");
        }

        return ManageSol[str1.length()][str2.length()].solution;
    }

    static int minimum(int x, int y)
    {
        if(x >= y)
            return x;
        return y;
    }

    static Solution minimum(int Ins, int Del, int Replace)
    {

        Solution solution = null;
        if(Ins <= Del && Ins <= Replace)
        {
            solution = new Solution();
            solution.operation = 1;
            solution.solution = Ins;
            return solution;
        }
        else if(Del <= Ins && Del <= Replace)
        {
            solution = new Solution();
            solution.operation = 2;
            solution.solution = Del;
            return solution;
        }
        else
        {
            solution = new Solution();
            solution.solution = Replace;
            solution.operation = 0;
            return solution;
        }
    }

    //my failure, function that should display steps
    static void path(Solution[][] ManagerSol, int i, int j, String str1, String str2)
    {
        if(ManagerSol[i][j].operation == 0)
        {
            System.out.printf("\nReplace %s -> %s", str1.charAt(i-1), str2.charAt(j-1));
            if(i > 1 && j > 1)
                path(ManagerSol, i-1,j-1, str1, str2);
        }
        if(ManagerSol[i][j].operation == 1)
        {
            System.out.printf("\nAdd %s on position %s", str2.charAt(j-1), i-1);
            if(j > 1)
                path(ManagerSol, i,j-1, str1, str2);
        }
        if(ManagerSol[i][j].operation == 2)
        {
            System.out.printf("\nDelete %s", str1.charAt(i-1));
            if(j > 1)
                path(ManagerSol, i-1,j, str1, str2);
        }
    }
}

小猫到坐着的输出:

&#13;
&#13;
[0,0]:(0,3) [0,1]:(1,3) [0,2]:(2,3) [0,3]:(3,3) [0,4]:(4,3) [0,5]:(5,3) [0,6]:(6,3) [0,7]:(7,3) 
[1,0]:(1,3) [1,1]:(1,0) [1,2]:(2,1) [1,3]:(3,1) [1,4]:(4,1) [1,5]:(5,1) [1,6]:(6,1) [1,7]:(7,1) 
[2,0]:(2,3) [2,1]:(2,2) [2,2]:(1,0) [2,3]:(2,1) [2,4]:(3,1) [2,5]:(4,1) [2,6]:(5,1) [2,7]:(6,1) 
[3,0]:(3,3) [3,1]:(3,2) [3,2]:(2,2) [3,3]:(1,0) [3,4]:(2,1) [3,5]:(3,1) [3,6]:(4,1) [3,7]:(5,1) 
[4,0]:(4,3) [4,1]:(4,2) [4,2]:(3,2) [4,3]:(2,2) [4,4]:(1,0) [4,5]:(2,1) [4,6]:(3,1) [4,7]:(4,1) 
[5,0]:(5,3) [5,1]:(5,2) [5,2]:(4,2) [5,3]:(3,2) [5,4]:(2,2) [5,5]:(2,0) [5,6]:(3,1) [5,7]:(4,1) 
[6,0]:(6,3) [6,1]:(6,2) [6,2]:(5,2) [6,3]:(4,2) [6,4]:(3,2) [6,5]:(3,2) [6,6]:(2,0) [6,7]:(3,1) 
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:2)

一般来说,你的想法是正确的。它甚至比那更简单。您无需存储任何其他信息。

您可以向后(从给定字符串的结尾开始)并以下列方式使用动态编程值:

  1. 如果其中一个索引为0,则只有一种方法可循。

  2. 否则,您可以“向后”查看3个可能的转换(从(i,j)到(i - 1,j - 1),(i - 1,j)和(i,j - 1) ))并选择产生(i,j)实际值的那个。如果有多种可能的选项,您可以选择其中任何一种。

  3. 一旦你知道从给定的一对位置去哪里,操作就是唯一确定的。

答案 1 :(得分:1)

我不熟悉Java,但这是JavaScript中的一个例子:

var a = 'kitten',
    b = 'sitting';

var m = new Array(a.length + 1);

for (var i=0; i<m.length; i++){
  m[i] = new Array(b.length + 1);
  
  for (var j=0; j<m[i].length; j++){
    if (i === 0) m[i][j] = j;
    if (j === 0) m[i][j] = i;
  }
}

for (var i=1; i<=a.length; i++){
  for (var j=1; j<=b.length; j++){

    // no change needed
    if (a[i - 1] === b[j - 1]){
      m[i][j] = m[i - 1][j - 1];
  
    // choose deletion or insertion
    } else {
      m[i][j] = Math.min(m[i - 1][j], m[i][j - 1], m[i - 1][j - 1]) + 1;
    }
  }
}

console.log('a: ' + JSON.stringify(a));
console.log('b: ' + JSON.stringify(b));

var i = a.length,
    j = b.length,
    steps = '';
    
while (i !== 0 && j !== 0){
  if (a[i - 1] === b[j - 1]){
    steps = 'no change; ' + steps;
    i--;
    j--;
    
  } else if (m[i - 1][j] < m[i][j - 1]){
    steps = 'delete \'' + a[i - 1] + '\'; ' + steps;
    i--;
    
  } else if (m[i - 1][j] === m[i][j - 1]){
    steps = 'replace \'' + a[i - 1] + '\' with \'' + b[j - 1] + '\'; ' + steps;
    i--;
    j--;
    
  } else {
    steps = 'insert \'' + b[j - 1] + '\'; ' + steps;
    j--;
  }
}

if (i === 0 && j > 0){
  steps = 'insert first ' + j + ' elements from b; ' + steps;
  
} else if (j === 0 && i > 0){
  steps = 'delete first ' + i + ' elements from a; ' + steps;
}

console.log('\n' + steps[0].toUpperCase() + steps.substr(1));

console.log('\nMatrix:\n');

for (var i in m){
  console.log(JSON.stringify(m[i]));
}