Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 编辑距离递归算法——Skiena_C++_C_Algorithm_Dynamic Programming - Fatal编程技术网

C++ 编辑距离递归算法——Skiena

C++ 编辑距离递归算法——Skiena,c++,c,algorithm,dynamic-programming,C++,C,Algorithm,Dynamic Programming,我在读史蒂文·斯基纳的算法设计手册,我在读动态规划一章。他有一些编辑距离的示例代码,并使用了一些书中或互联网上都没有解释的功能。所以我想知道 a) 这个算法是如何工作的 b) indel和match函数的作用是什么 #define MATCH 0 /* enumerated type symbol for match */ #define INSERT 1 /* enumerated type symbol for insert */ #define DEL

我在读史蒂文·斯基纳的算法设计手册,我在读动态规划一章。他有一些编辑距离的示例代码,并使用了一些书中或互联网上都没有解释的功能。所以我想知道

a) 这个算法是如何工作的

b) indel和match函数的作用是什么

#define MATCH     0       /* enumerated type symbol for match */
#define INSERT    1       /* enumerated type symbol for insert */
#define DELETE    2       /* enumerated type symbol for delete */

int string_compare(char *s, char *t, int i, int j)
{
        int k;                  /* counter */
        int opt[3];             /* cost of the three options */
        int lowest_cost;        /* lowest cost */

        if (i == 0) return(j * indel(' '));
        if (j == 0) return(i * indel(' '));

        opt[MATCH] = string_compare(s,t,i-1,j-1) + match(s[i],t[j]);
        opt[INSERT] = string_compare(s,t,i,j-1) + indel(t[j]);
        opt[DELETE] = string_compare(s,t,i-1,j) + indel(s[i]);

        lowest_cost = opt[MATCH];
        for (k=INSERT; k<=DELETE; k++)
                if (opt[k] < lowest_cost) lowest_cost = opt[k];

        return( lowest_cost );
}
#为匹配定义匹配0/*枚举类型符号*/
#为INSERT定义INSERT 1/*枚举类型符号*/
#为DELETE定义DELETE 2/*枚举类型符号*/
int字符串_比较(char*s,char*t,inti,intj)
{
int k;/*计数器*/
int opt[3];/*三个选项的成本*/
int最低成本;/*最低成本*/
如果(i==0)返回(j*indel(“”));
如果(j==0)返回(i*indel(“”));
opt[MATCH]=字符串_比较(s,t,i-1,j-1)+匹配(s[i],t[j]);
opt[INSERT]=string_compare(s,t,i,j-1)+indel(t[j]);
opt[DELETE]=string_compare(s,t,i-1,j)+indel(s[i]);
最低成本=选择[匹配];

对于(k=INSERT;k它们在本书中进行了解释。请阅读第8.2.4节各种编辑距离基本上,它使用了解决问题的动态规划方法,其中问题的解决方案被构造为子问题的解决方案,以避免自下而上或自上而下的重新计算

问题的递归结构如下所示,其中
i,j
分别是两个字符串中的开始(或结束)索引

这里有一段摘录,很好地解释了算法

问题:给定两个大小为m、n的字符串和一组操作替换 (R) ,插入(I)和删除(D)所有内容,费用相同。查找最小数量 将一个字符串转换为另一个字符串所需的编辑(操作)

识别递归方法:

这种情况下会出现什么子问题?考虑查找编辑距离 对于部分字符串,请使用小前缀。让我们将它们表示为 [1…i]和[1…j]对于一些1 在前缀中,我们可以用三种方式右对齐字符串(i,-), (,j)和(i,j)。连字符符号(-)不代表任何字符 举个例子可以更清楚地说明这一点

给定字符串星期天和星期六。我们希望将星期天转换为 星期六,编辑最少。让我们选择i=2和j=4,即前缀 字符串分别为SUN和SATU(假设字符串为索引 从1开始)。最右边的字符可以三个对齐 不同的方式

情况1:对齐字符U和U。它们相等,不需要编辑。 剩下的问题是i=1和j=3,E(i-1,j-1)

案例2:将第一个字符串中的右字符对齐,而不将第一个字符串中的任何字符对齐 第二个字符串。我们需要在这里删除(D)。我们仍然有问题 对于i=1和j=4,E(i-1,j)

案例3:对齐第二个字符串中的右字符,而不对齐第二个字符串中的任何字符 第一个字符串。我们需要在这里插入(I)。我们仍然保留 i=2和j=3的问题,E(i,j-1)

组合所有子问题使对齐前缀字符串的成本最小 在i和j处结束,由

E(i,j)=min([E(i-1,j)+D],[E(i,j-1)+i],[E(i-1,j-1)+R如果 i、 j个字符不相同])

我们还没有完成。基本情况是什么

当两个字符串的大小都为0时,成本为0。当只有一个字符串时 字符串的值为零,我们需要像非零的值一样进行编辑操作 长度字符串。数学上

E(0,0)=0,E(i,0)=i,E(0,j)=j

我建议你仔细解释一下


如果两个字符不匹配,函数
match()
返回1(以便在最终答案中添加一个移动),否则返回0。

本书第287页:

int match(char c, char d)
{
  if (c == d) return(0); 
  else return(1); 
}

int indel(char c)
{
  return(1);
}

请浏览此链接:

实现上述算法的代码是:

int dpEdit(char *s1, char *s2 ,int len1,int len2)
{
if(len1==0)  /// Base Case
return len2;
else if(len2==0)
return len1;
else
{
    int add, remove,replace;
    int table[len1+1][len2+2];
    for(int i=0;i<=len2;i++)
    table[0][i]=i;
    for(int i=0;i<=len1;i++)
    table[i][0]=i;
    for(int i=1;i<=len1;i++)
    {
        for(int j=1;j<=len2;j++)
        {
          // Add 
          //
          add = table[i][j-1]+1;  
          remove = table[i-1][j]+1;
          if(s1[i-1]!=s2[j-1])
          replace = table[i-1][j-1]+1;
          else
          replace =table[i-1][j-1];
          table[i][j]= min(min(add,remove),replace); // Done :)

        }
    }
int-dpEdit(char*s1、char*s2、int-len1、int-len2)
{
if(len1==0)///基本情况
返回len2;
else if(len2==0)
返回len1;
其他的
{
int添加、删除、替换;
int表[len1+1][len2+2];

对于(int i=0;i这是一个递归算法,不是动态规划。请注意,当算法启动时,i&j分别指向s&t的最后一个字符

indel返回1。 如果a=b(匹配),则match(a,b)返回0,否则返回1(替换)

#为匹配定义匹配0/*枚举类型符号*/
#为INSERT定义INSERT 1/*枚举类型符号*/
#为DELETE定义DELETE 2/*枚举类型符号*/
int字符串_比较(char*s,char*t,inti,intj)
{
int k;/*计数器*/
int opt[3];/*三个选项的成本*/
int最低成本;/*最低成本*/
//基本情况下,如果i为0,则我们到达s和的开头
//现在它是空的,所以s&t之间有j*1编辑距离
//想想看,如果s最初是空的,而t不是空的,有多少个
//我们需要在s上执行的编辑与t类似?答案是在哪里
//我们现在在t,也就是j
如果(i==0)返回(j*indel(“”));
//与上述推理相同,但适用于s而非t
如果(j==0)返回(i*indel(“”));
//通过检查s[i]=t[j]计算opt[match],如果为真,则为0;如果为非真,则为1
//然后递归地对s[i-1]&t[j-1]执行相同的操作
opt[MATCH]=字符串_比较(s,t,i-1,j-1)+匹配(s[i],t[j]);
//计算opt[insert],这是我们需要插入的字符数
//在s中使它看起来像t,或者从另一个角度看,
//我们需要从t中删除多少个字符才能使其与s相似?
//因为我们从t中删除,所以我们将j减少1,留下i(指针)
//在s)as is+indel(t[j])中,我们总是删除它
#define MATCH     0       /* enumerated type symbol for match */
#define INSERT    1       /* enumerated type symbol for insert */
#define DELETE    2       /* enumerated type symbol for delete */

int string_compare(char *s, char *t, int i, int j)
{
    int k;                  /* counter */
    int opt[3];             /* cost of the three options */
    int lowest_cost;        /* lowest cost */

    // base case, if i is 0, then we reached start of s and 
    // now it's empty, so there would be j * 1 edit distance between s & t
    // think of it if s is initially empty and t is not, how many
    // edits we need to perform on s to be similar to t? answer is where
    // we are at t right now which is j
    if (i == 0) return(j * indel(' '));
    // same reasoning as above but for s instead of t
    if (j == 0) return(i * indel(' '));

    // calculate opt[match] by checking if s[i] = t[j] which = 0 if true or 1 if not
    // then recursively do the same for s[i-1] & t[j-1]
    opt[MATCH] = string_compare(s,t,i-1,j-1) + match(s[i],t[j]);
    // calculate opt[insert] which is how many chars we need to insert 
    // in s to make it looks like t, or look at it from the other way,
    // how many chars we need to delete from t to make it similar to s?
    // since we're deleting from t, we decrease j by 1 and leave i (pointer
    // in s) as is + indel(t[j]) which we deleted (always returns 1)
    opt[INSERT] = string_compare(s,t,i,j-1) + indel(t[j]);
    // same reasoning as before but deleting from s or inserting into t
    opt[DELETE] = string_compare(s,t,i-1,j) + indel(s[i]);

    // these lines are just to pick the min of opt[match], opt[insert], and
    // opt[delete]
    lowest_cost = opt[MATCH];
    for (k=INSERT; k<=DELETE; k++)
            if (opt[k] < lowest_cost) lowest_cost = opt[k];

    return( lowest_cost );
}