编辑距离矩阵

2024-04-06

我正在尝试构建一个程序,该程序接受两个字符串并为它们填充编辑距离矩阵。让我困惑的是,对于第二个字符串输入,它跳过了第二个输入。我尝试使用 getch() 清除缓冲区,但没有成功。我也尝试过切换到 scanf(),但这也导致了一些崩溃。请帮助!

Code:

#include <stdio.h>
#include <stdlib.h>

int min(int a, int b, int c){
    if(a > b && a > c)
        return a;
    else if(b > a && b > c)
        return b;
    else
        return c;
}

int main(){

    // allocate size for strings
    int i, j;
    char *input1 = (char*)malloc(sizeof(char)*100);
    char *input2 = (char*)malloc(sizeof(char)*100);

    // ask for input
    printf("Enter the first string: ");
    fgets(input1, sizeof(input1), stdin);
    printf("\nEnter the second string: ");
    fgets(input2, sizeof(input2), stdin);

    // make matrix
    int len1 = sizeof(input1), len2 = sizeof(input2);
    int c[len1 + 1][len2 + 1];

    // set up input 2 length
    for(i = 0; i < len2 + 1; i++){
        c[0][i] = i;
    }

    // set up input 1 length
    for(i = 0; i < len1 + 1; i++){
        c[i][0] = i;
    }

    // fill in the rest of the matrix
    for(i = 1; i < len1; i++){
        for(j = 1; j < len2; j++){
            if(input1[i] == input2[j]) // if the first letters are equal make the diagonal equal to the last
                c[i][j] = c[i - 1][j - 1];
            else
                c[i][j] = 1 + min(c[i - 1][j - 1], c[i - 1][j], c[i][j - 1]);
        }
    }

    // print the matrix
    printf("\n");
    for(j = 0; j < len2; j++){
        for(i = 0; i < len1; i++){
            printf("|  %d", c[i][j]);
        }
        printf("\n");
    }

    return 1;
}

坚持fgets.

正如其他人指出的那样,使用char input1[100]代替char *input1 = malloc(...)

但是,即使有了这样的变化,这使得sizeof里面的fgets正确,使用sizeof设置时len1 and len2是错的。您将处理一个entire100 个缓冲区,即使其中只有 10 个有效字符(即其余字符未定义/随机)。

你[可能]想要的是strlen[和换行符] 以获得实际有用的长度。

这是修改后的代码[请原谅无偿的风格清理]:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
min(int a, int b, int c)
{
    if (a > b && a > c)
        return a;
    if (b > a && b > c)
        return b;
    return c;
}

int
main(void)
{

    // allocate size for strings
    int i;
    int j;
    char input1[100];
    char input2[100];

    // ask for input
    printf("Enter the first string: ");
    fgets(input1, sizeof(input1), stdin);
    int len1 = strlen(input1);
    if (input1[len1 - 1] == '\n') {
        input1[len1 - 1] = 0;
        --len1;
    }

    printf("\nEnter the second string: ");
    fgets(input2, sizeof(input2), stdin);
    int len2 = strlen(input2);
    if (input2[len2 - 1] == '\n') {
        input2[len2 - 1] = 0;
        --len2;
    }

    // make matrix
    int c[len1 + 1][len2 + 1];

    // set up input 2 length
    for (i = 0; i < len2 + 1; i++) {
        c[0][i] = i;
    }

    // set up input 1 length
    for (i = 0; i < len1 + 1; i++) {
        c[i][0] = i;
    }

    // fill in the rest of the matrix
    for (i = 1; i < len1; i++) {
        for (j = 1; j < len2; j++) {
            // if the 1st letters are equal make the diagonal equal to the last
            if (input1[i] == input2[j])
                c[i][j] = c[i - 1][j - 1];
            else
                c[i][j] = 1 + min(c[i - 1][j - 1], c[i - 1][j], c[i][j - 1]);
        }
    }

    // print the matrix
    printf("\n");
    for (j = 0; j < len2; j++) {
        for (i = 0; i < len1; i++) {
            printf("|  %d", c[i][j]);
        }
        printf("\n");
    }

    return 1;
}

UPDATE:

好吧,亲爱的,我明白你的意思了!我尝试使用 malloc 的原因是为了避免制作必须打印 100x100 空格大小的矩阵。

与固定尺寸input1 or the malloced one, fgets只会将其填充到输入的输入大小[如有必要,剪裁到第二个参数]。但是,它确实not填充/填充缓冲区的剩余部分anything(例如右侧的空格)。什么does要做的就是在从输入读取的最后一个字符[通常是换行符]之后添加一个 EOS [字符串结束]字符[这是一个二进制 0x00]。

因此,如果输入字符串是:abcdef\n,长度[可从strlen] 为 7,输入[7] 将为 0x00,并且input1[8]通过input1[99]将具有未定义/随机/不可预测的值并且not spaces.

由于换行符不是很有用,因此通常在进一步处理之前将其删除。例如,在计算小短语的编辑距离时,它并不是非常相关。

使用 strlen() 是否只计算数组内的字符数,还是也包括所有空格?

正如我上面提到的,fgets does not将字符串填充在end,所以,不用担心。它会做你想要/期望的事情。

strlen只计算 [但是not包括 EOS 终止符(即零)]。如果其中一些字符恰好是空格,那么它们will被计算为strlen——这就是我们想要的。

考虑计算以下任意两个之间的编辑距离phrases:

quick brown fox jumped over the lazy dogs
the quick brown fox jumped over lazy dogs
quick brown fox jumps over the lazy dog

在每种情况下,我们want strlen在长度计算中包括[内部/嵌入]空格。那是因为它is计算短语的编辑距离完全有效。


有一个有效的用法malloc:当数据量太大而无法放入堆栈时。大多数系统都有默认限制(例如在 Linux 下,为 8 MB)。

假设我们正在计算两本书章节的编辑距离[从文件中读取],我们会有(例如):

char input1[50000];
char input2[50000];

上面的内容是合适的,但是c矩阵会导致堆栈溢出:

int c[50000][50000];

因为这个的大小是50000 * 50000 * 4大约为 9.3 GB。

因此,为了容纳所有这些数据,我们需要将其分配在堆上。虽然可以做malloc for c and维护 2D 矩阵访问,我们必须创建一个函数并将指针传递给c to it.

因此,这是一个修改版本,它接受任意大尺寸的输入:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#define sysfault(_fmt...) \
    do { \
        fprintf(stderr,_fmt); \
        exit(1); \
    } while (0)

#define C(y,x)      c[((y) * (len2 + 1)) + (x)]

long
min(long a, long b, long c)
{
    if (a > b && a > c)
        return a;
    if (b > a && b > c)
        return b;
    return c;
}

char *
input(const char *prompt,long *lenp,const char *file)
{
    FILE *fp;
    char *lhs;
    int chr;
    long siz;
    long len;

    if (file != NULL)
        fp = fopen(file,"r");
    else {
        fp = stdin;
        printf("Enter %s string: ",prompt);
        fflush(stdout);
    }

    lhs = NULL;
    siz = 0;
    len = 0;

    while (1) {
        chr = fgetc(fp);
        if (chr == EOF)
            break;

        if ((chr == '\n') && (file == NULL))
            break;

        // grow the character array
        if ((len + 1) >= siz) {
            siz += 100;
            lhs = realloc(lhs,siz);
            if (lhs == NULL)
                sysfault("input: realloc failure -- %s\n",strerror(errno));
        }

        lhs[len] = chr;
        len += 1;
    }

    if (file != NULL)
        fclose(fp);

    if (lhs == NULL)
        sysfault("input: premature EOF\n");

    // add the EOS
    lhs[len] = 0;

    // return the length to the caller
    *lenp = len;

    return lhs;
}

int
main(int argc,char **argv)
{
    long i;
    long j;
    char *input1;
    long len1;
    char *input2;
    long len2;
    long *c;

    --argc;
    ++argv;

    switch (argc) {
    case 2:
        input1 = input("first",&len1,argv[0]);
        input2 = input("second",&len2,argv[1]);
        break;
    default:
        input1 = input("first",&len1,NULL);
        input2 = input("second",&len2,NULL);
        break;
    }

    // make matrix
    c = malloc(sizeof(*c) * (len1 + 1) * (len2 + 1));
    if (c == NULL)
        sysfault("main: malloc failure -- %s\n",strerror(errno));

    // set up input 2 length
    for (i = 0; i < len2 + 1; i++) {
        C(0,i) = i;
    }

    // set up input 1 length
    for (i = 0; i < len1 + 1; i++) {
        C(i,0) = i;
    }

    // fill in the rest of the matrix
    for (i = 1; i < len1; i++) {
        for (j = 1; j < len2; j++) {
            // if the 1st letters are equal make the diagonal equal to the last
            if (input1[i] == input2[j])
                C(i,j) = C(i - 1,j - 1);
            else
                C(i,j) = 1 + min(C(i - 1,j - 1), C(i - 1,j), C(i,j - 1));
        }
    }

    // print the matrix
    printf("\n");
    for (j = 0; j < len2; j++) {
        for (i = 0; i < len1; i++) {
            printf("|  %ld", C(i,j));
        }
        printf("\n");
    }

    return 1;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编辑距离矩阵 的相关文章

  • 从实体获取单列

    如何从查询中获取单个列而不是整个对象 我可以这样做来获取整个对象 但我想要的只是名称 IList
  • std::list::clear 是否会使 std::list::end 迭代器无效?

    检查这个代码 include stdafx h include
  • C# 和月历,选择多个日期

    我正在制作一个程序 可以帮助人们用 C 为某个部门 预订 订单 他们需要能够选择不同月份的多个日期 我更愿意拥有它 这样他们就可以单击一个日期 然后按住 Shift 键单击另一个日期以选择这两个日期之间的所有日期 并控制单击以进行单选 取消
  • OpenGL缓冲区更新[重复]

    这个问题在这里已经有答案了 目前我正在编写一个模拟水的程序 以下是我所做的步骤 创建水面 平面 创建VAO 创建顶点缓冲区对象 在其中存储法线和顶点 将指针绑定到此 VBO 创建索引缓冲区对象 然后我使用 glDrawElements 渲染
  • libtool 在 Ubuntu 13.04 上构建 thrift 0.9.1 时出错

    在 Ubuntu 13 04 上构建 thrift 0 9 1 支持 C C java C perl python 时出现此错误 configure 不带任何选项运行 make 不带任何选项运行 Making all in test mak
  • 如何查明 .exe 是否正在 C++ 中运行?

    给定进程名称 例如 程序 exe C 标准库没有这样的支持 您需要一个操作系统 API 来执行此操作 如果这是 Windows 那么您将使用 CreateToolhelp32Snapshot 然后使用 Process32First 和 Pr
  • make_shared<>() 中的 WKWYL 优化是否会给某些多线程应用程序带来惩罚?

    前几天我偶然看到这个非常有趣的演示 http channel9 msdn com Events GoingNative GoingNative 2012 STL11 Magic Secrets作者 Stephan T Lavavej 其中提
  • Nhibernate:连接表并从其他表获取单列

    我有以下表格 create table Users Id uniqueidentifier primary key InfoId uniqueidentifier not null unique Password nvarchar 255
  • C# Winforms Designer 无法打开,因为它无法在同一程序集中找到类型

    我收到以下错误 找不到类型 My Special UserControl 请确保引用包含此类型的程序集 如果此类型是您的开发项目的一部分 请确保已使用当前平台或任何 CPU 的设置成功构建该项目 但没有任何意义的是My Special Us
  • 判断串口是普通COM还是SPP

    我正在寻找一种方法来确定 COM 是标准 COM 还是 SPP COM 也称为 COM 设备的电缆替换蓝牙适配器 我有一个可以在 USB COM gt USB 和蓝牙下工作的设备 并且蓝牙接口可以与 SPP 一起工作 我目前正在使用Syst
  • C 类型命名约定,_t 或 ALLCAPS

    我一直想知道是否有任何命名约定 例如何时对类型使用全部大写以及何时追加 t 什么时候不使用任何东西 我知道当时 K R 发布了各种有关如何使用 C 的文档 但我找不到任何相关内容 在 C 标准库类型中 t看起来漂亮占主导地位 time t
  • 提升mapped_file_source、对齐方式和页面大小

    我正在尝试在性能很重要的上下文中解析一些大小高达几百兆字节的文本文件 因此我使用 boostmapped file source 解析器期望源以空字节终止 因此我想检查文件大小是否是页面大小的精确倍数 如果是 则使用较慢的非内存映射方法 我
  • 名称查找、实例化点 (POI) 和基本类型

    以下代码针对 X 进行编译 但不适用于 double struct X void foo double void foo X namespace NN struct A void foo A foo double error foo not
  • 在 C 语言中替换宏内的宏

    我正在尝试使代码部分可重用 我下面的评论片段没有达到我想要的效果 define NAME ABC define LOG SIZE NAME LEN 我想LOG SIZE决心ABC LEN 我尝试过使用 但没能让它发挥作用 LOG SIZE在
  • WPF DataGrid - 在每行末尾添加按钮

    我想在数据网格的每一行的末尾添加一个按钮 我找到了以下 xaml 但它将按钮添加到开头 有人知道如何在所有数据绑定列之后添加它吗 这会将按钮添加到开头而不是末尾
  • 如何测试某些代码在 C++ 中无法编译? [复制]

    这个问题在这里已经有答案了 可能的重复 单元测试编译时错误 https stackoverflow com questions 605915 unit test compile time error 我想知道是否可以编写一种单元测试来验证给
  • 解释这段代码的工作原理;子进程如何返回值以及在哪里返回值?

    我不明白子进程如何返回该值以及返回给谁 输出为 6 7 问题来源 http www cs utexas edu mwalfish classes s11 cs372h hw sol1 html http www cs utexas edu
  • 绘制多边形

    我正在使用 Google Maps API V3 根据路径绘制多边形 该路径是随机未排序坐标点 LatLng 的数组 这会产生以下形状 Polylines intersect Problem 由于多边形的形状取决于路径中点的顺序 因此如何对
  • 在 C 中使用 #define 没有任何价值

    If a define没有任何价值地使用 例如 define COMMAND SPI 默认值是0吗 不 它的评估结果为零 从字面上看 该符号被替换为空 然而 一旦你有了 define FOO 预处理器条件 ifdef FOO现在将是真的 另
  • 如何在c中断言两个类型相等?

    在 C 中如何断言两种类型相等 在 C 中 我会使用 std is same 但搜索 StackOverflow 和其他地方似乎只能给出 C 和 C 的结果 在C中没有办法做到这一点吗 请注意 这不是询问变量是否具有某种类型 而是询问两个类

随机推荐

  • Android——在 OnDrawFrame 方法之外将 GLSurfaceView.Renderer 置于睡眠状态(如 Thread.sleep(20))

    我想控制 GLSurfaceView Renderer 的渲染速率 我在扩展 GLSurfaceView 的类中实现了一个线程 并在 while true 循环中定期将其置于睡眠状态 这不会减慢渲染器的速度 有一个很好的答案here htt
  • 自旋锁与信号量

    信号量和自旋锁之间的基本区别是什么 我们什么时候会使用信号量而不是自旋锁 自旋锁和信号量主要有四个不同点 1 它们是什么 A spinlock是锁的一种可能实现 即通过忙等待 旋转 实现的锁 信号量是锁的概括 或者 相反 锁是信号量的特例
  • 带有节标题的列表视图android

    在 android listview gt Headerbar section 中是否有可能不滚动 直到该部分的列表不滚动 就像 iPhone 的桌面视图一样 我使用了部分列表视图 但我想要像这个 iphone 表格视图 有没有可能 谢谢
  • Jenkins 在 ClearCase 中创建视图

    我正在使用 Jenkins 和 ClearCase 进行自动构建 但遇到了问题 我编写了一个批处理脚本 使用cleartool命令mkview在ClearCase中创建视图 当我通过单击脚本来执行该脚本时 一切正常 视图是在 ClearCa
  • 解析在tinyxml中

    如何在 TinyXML 中解析以下内容
  • netstandard 1.5 中的 BinaryFormatter

    根据 NET CoreFx API 及其关联的 NET 平台标准版本列表 https github com dotnet corefx blob master Documentation architecture net platform
  • 在 .Net 中使用私有集初始化属性

    public class Foo public string Name get private set lt Because set is private void Main var bar new Foo Name baz lt This
  • 二维数组作为函数的参数

    为什么不能像处理普通数组一样在函数中声明二维数组参数 void F int bar Ok void Fo int bar Not ok void Foo int bar SIZE Ok 为什么需要声明列的大小 静态数组 你似乎没有完全明白这
  • 如何在yii2高级模板中上传web文件夹中的文件?

    我尝试在后端上传文件 每次上传文件时 它都会成功上传并成功保存在数据库中 但它没有保存到我指定的目录中 因此我的应用程序找不到该文件 并且我已经给出了 777对 web 目录中的 uploads 文件夹的权限 下面是我的代码 处理和保存文件
  • 如何使用 Compact Framework 在 C# 中验证 X.509 证书

    我正在尝试使用 C 和 NetCF 验证 X 509 证书 我有 CA 证书 如果我理解正确的话 我需要使用该 CA 证书中的公钥来解密不受信任的证书的签名 这应该给我不可信证书的计算哈希值 然后我应该自己计算证书的哈希值并确保两个值匹配
  • Swift组合:使用其他发布者(使用CombineLatest)的后续发布者不会“触发”

    我正在尝试复制 WWDC 2019 会议 实践中组合 中给出的 向导学校注册 示例https developer apple com videos play wwdc2019 721 https developer apple com vi
  • 属性的访问器实现

    是否有一些文档说明编译器如何自动生成属性的访问器 当编写自定义访问器 覆盖合成的访问器 时 最好了解原始实现 特别是要查看具有不同 弱 强 保留 复制等 属性的属性的访问器的不同实现 是否有一些文档说明编译器如何自动生成属性的访问器 编译器
  • 从 openstreetmap 获取城市边界

    我正在开发一个网站 我需要根据用户输入获取某个区域的所有边界 例如 用户想知道名为 x 的城市的边界 我应该如何从 openstreetmap 获取它 我听说过 xapi 和 osmosis 但在任何地方都找不到任何例子 谢谢 我在这里尝试
  • 使用media3库时添加MediaItem导致错误

    我正在使用最新的Android Media3库 但是我在使用它时发现了一个问题 我创建了一个媒体会话服务 然后得到MediaController中的Activity 然后当我尝试调用媒体控制器并添加一些 MediaItem 时 发生错误 j
  • Python/PyODBC 通过 IP 与可信连接连接到 SQL Server 2008 DB

    如果有人问这个问题 我提前道歉 尽管我发现了类似的问题 但我找不到正确的答案 我正在尝试通过使用可信连接的 IP 端口来连接到 SQL Server 2008 DB 另外一点复杂性是 数据库位于美国境外 通常我们通过 Citrix 登录 登
  • 告诉编译器泛型返回类型不借用任何对参数的引用?

    tldr gt 给定一个接受通用回调参数并返回关联类型的特征函数 编译器会抱怨关联类型可能从回调函数借用参数 有没有办法告诉编译器事实并非如此 细节 我计划实现一个接受回调参数的特征函数 并希望强制该特征函数的实现实际调用该回调 我通过让回
  • 保证文件关闭

    我有一个类 在构造函数中创建一个文件对象 该类还实现了 finish 方法作为其接口的一部分 在该方法中我关闭了文件对象 问题是 如果我在此之前遇到异常 文件将不会被关闭 相关类还有许多使用文件对象的其他方法 我需要将所有这些包装在一个最后
  • REST API 资源命名约定 - 用户或用户(复数)

    长版 对于某些人 包括我自己 来说 构建 REST API 过程中最痛苦 最令人头疼的部分之一是确定每个资源及其随附端点的名称 当然 这取决于个人喜好 有些事情是受到社区鼓励的 例如 大多数人 包括我 都会将他们的资源名称复数 GET no
  • 如何从日期时间获取时间跨度

    设想 第三方网络服务退货datetime在两个单独的字段中 即日期和时间 我需要一种连接成单个字段的方法 e g startDate 24 06 2012 startTime 1 01 1970 1 00 00 AM Expected re
  • 编辑距离矩阵

    我正在尝试构建一个程序 该程序接受两个字符串并为它们填充编辑距离矩阵 让我困惑的是 对于第二个字符串输入 它跳过了第二个输入 我尝试使用 getch 清除缓冲区 但没有成功 我也尝试过切换到 scanf 但这也导致了一些崩溃 请帮助 Cod