在Visual C#中匹配字符串中的字符

3
我正在使用Visual C#编写代码,用于计算单词错误率。我有一个文本框用于参考答案,即正确的句子,还有一个用于假设答案,即错误的句子。
为了计算WER,我需要计算以下三种情况:替换(被更改的单词),插入(在句子中添加的单词)和删除(从原始句子中删除的单词)。
例如: 参考答案:This is a NPL program. 假设答案:it is an NPL cool.
其中: it: 替换 is: 正确 an: 替换 NPL: 正确 program: 删除 cool: 插入
我尝试了dasblinkenlight提出的算法(非常感谢),它可以运行,但是在某一行出现了运行时错误,我无法解决。
int x=  Compute(buffer[j], buffer_ref[i]);

数组索引超出范围。

这是我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        string [] hyp = new string[20];
        string [] refrence = new string[20];
        string [] Anser= new string[20];
        string[] buffer = new string[20];
        string[] buffer_ref = new string[20];
        int count = 0; // number of words 
        string ref2=" " ;
        string hyp2 = " ";
        string Anser2 = " ";
        string buffer2 = " ";

        int corecct_c=0;
        int corecct_d = 0;
        int corecct_i = 0;

        //====================================================================

        public Form1()
        {
            InitializeComponent();
            for (int i = 0; i <= 19; ++i)
            {
                hyp[i] = null;
                buffer[i] = null;
            }
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            refrence = this.textBox2.Text.Split(' ');
            buffer_ref = this.textBox2.Text.Split(' ');


        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            hyp = this.textBox1.Text.Split(' ');
            buffer = this.textBox1.Text.Split(' ');
            //hyp = this.textBox1.Text;
            // fname1.Add(this.textBox1.Text);


        }

        public void correct(string[] R)
        {

            for (int i = 0; (i <= 19) && (R[i] != "."); ++i)
            {

                if (buffer[i] == refrence[i])
                { buffer[i] = "0";
                buffer_ref[i] = "0";
                    corecct_c = corecct_c + 1;
                    Anser[i] = "C";
                }
            }

        }

        // function that compute 2 strings
        public static int Compute(string s, string t)
        {
            int n = s.Length;
            int m = t.Length;
            int[,] d = new int[n + 1, m + 1];

            // Step 1
            if (n == 0)
            {
                return m;
            }

            if (m == 0)
            {
                return n;
            }

            // Step 2
            for (int i = 0; i <= n; d[i, 0] = i++)
            {
            }

            for (int j = 0; j <= m; d[0, j] = j++)
            {
            }

            // Step 3
            for (int i = 1; i <= n; i++)
            {
                //Step 4
                for (int j = 1; j <= m; j++)
                {
                    // Step 5
                    int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;

                    // Step 6
                    d[i, j] = Math.Min(
                        Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
                        d[i - 1, j - 1] + cost);
                }
            }
            // Step 7
            return d[n, m];
        }


        public void sub(){

            for (int j = 0;j<=19;j++) 
         {
             if (buffer[j].IndexOf("0") != -1)
             {


                 for (int i = 0; i <= 19; i++)
                 {

                     if (buffer_ref[j].IndexOf("0") != -1)
                     {

                       int x=  Compute(buffer[j], buffer_ref[i]);
                       if (x > 3)
                       {
                           buffer[j] = "0";
                           Anser[j] = "S";

                       }


                     }//end if

                 } 

             }//end if 


        }//end for 

        }// end fun

        private void button1_Click(object sender, EventArgs e)
        {


            correct(refrence);
            sub();
            for (int i = 0; (i <= 19) && (refrence[i] != "."); ++i)
            {
                //loop intialize 
                ref2 = ref2 + " " + refrence[i];
                hyp2 = hyp2 + " " + hyp[i];
                Anser2 = Anser2 + " " + Anser[i];
                buffer2 = buffer2 + " " + buffer[i];
                count++;
                            }

            listBox1.Items.Add(" Refrence :" + ref2);
            listBox1.Items.Add(" HYp :" + hyp2);
            listBox1.Items.Add(" Anser:" + Anser2);
            listBox1.Items.Add(" buffer:" + buffer2);
            listBox1.Items.Add(count);

        } 




        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }



        private void button2_Click(object sender, EventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

    }
}

can you help me please ?


欢迎,需要提醒的是,我们已经有一些类似的问题,如 http://stackoverflow.com/questions/5344514/testing-for-similar-string-content、http://stackoverflow.com/questions/747169/c-sharp-comparing-similar-strings 和 https://dev59.com/iHI-5IYBdhLWcg3wTWj4。 - Nathan Koop
1
“相似”有多相似?两个字符串需要有多少相同的字母才能被认为是“相似”的? - Mikk
谢谢@NathanKoop,我就要提到这个;) - Benjamin Trent
我使用了莱文斯坦距离算法,但是我遇到了一些麻烦^^",有一个运行时错误我无法处理:( - Glory
2个回答

5

有一种内置方法可以测试两行是否相同,但没有内置方法可以告诉您两行是否类似。您需要实现一种测量字符串相似度的算法,例如Levenshtein Distance- 一种非常常见的Edit Distance算法。具有较小编辑距离的行可以根据特定于您要求的阈值被声明为相似。


2
+1 你更快了 :) Levenstein距离算法的C#实现:http://www.dotnetperls.com/levenshtein - Cristian Lupascu
你能否帮我检查一下我的代码?我觉得有些地方出了问题,但是我不知道具体是哪里。 - Glory
这是一种计算替换位置的方法。 - Glory
我已经写好了所有的代码,请问你能告诉我你的想法吗? - Glory
找到了我要找的东西..谢谢你的帮助^^ - Glory
显示剩余4条评论

2

你需要使用一种算法来比较两个字符串之间的“距离”:

The closeness of a match is measured in terms of the number of primitive operations necessary to convert the string into an exact match. This number is called the edit distance between the string and the pattern. The usual primitive operations are:

insertion: cot  coat
deletion: coat  cot
substitution: coat  cost

你能帮我检查一下我的代码吗?我觉得有哪里出了问题,但是不知道具体是哪里。 - Glory
你的代码中缓冲区(buffer)是做什么用的?要计算a1a2之间的“距离”,你需要执行以下操作:var distance = LevenshteinDistance.Compute(a1, a2) - Nathan Koop
缓冲区是一个临时区域,我可以在其中删除正确的单词,以便代码可以跳过它们。 - Glory

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接