C# 中的 Rabin-Karp 算法 [关闭]

Posted

技术标签:

【中文标题】C# 中的 Rabin-Karp 算法 [关闭]【英文标题】:Rabin-Karp Algorithm in C# [closed] 【发布时间】:2014-04-17 18:46:31 【问题描述】:

我已经在 C#.NET 中实现了 Rabin-Karp 算法,遵循这个伪代码:

问题是,模式与原始文本不匹配。我已经彻底浏览了代码,但我无法确定代码中的问题。有人可以告诉我代码中的错误吗?

static void Main(string[] args)

    string text = "ratcatpat catbats";
    string pattern = "cat";

    int d = text.Select(e => e).Distinct().Count();

    RabinCarp(text, pattern, d, 17);

    Console.ReadKey();


static void RabinCarp(string text, string pattern, int sizeOfAlphabet, int moduloValue)
 
    int rollingHashOf_P = 0;
    int rollingHashOf_T = 0;

    int lengthOfText = text.Length;
    int lengthOfPattern = pattern.Length;
    int h = (int)(Math.Pow(sizeOfAlphabet, lengthOfPattern - 1) % moduloValue);

    for (int i = 0; i < lengthOfPattern; i++)
    
        rollingHashOf_P = (sizeOfAlphabet * rollingHashOf_P + (int)pattern[i]) % moduloValue;
        rollingHashOf_T = (sizeOfAlphabet * rollingHashOf_T + (int)text[i]) % moduloValue;
    

    int diffNM = lengthOfText - lengthOfPattern;

    for (int i = 0; i <= diffNM; i++)
    
        if (Math.Abs(rollingHashOf_P) == Math.Abs(rollingHashOf_T))
        
            if (text.Substring(i, lengthOfPattern).Contains(pattern))
            
                string message = "pattern identified";
                Console.WriteLine(message);
            
           
        if (i < diffNM)
        
            rollingHashOf_T = Math.Abs(sizeOfAlphabet * (rollingHashOf_T - (int)text[i] * h) + (int)text[i + lengthOfPattern]) % moduloValue;
        
    

【问题讨论】:

你试过调试了吗? 拜托,我们大多数人也不会神奇地发现错误。我们必须努力在我们的代码中找到错误,剖析它,检查内部数据结构,对其进行模块化,测试不同的模块等。在您的情况下,第一步是验证子字符串哈希实际上是否计算正确。您可以将Math.Abs(sizeOfAlphabet * (rollingHashOf_T - (int)text[i] * h) + (int)text[i + lengthOfPattern]) 行提取到它自己的函数中,并检查它是否为相等的子字符串返回相同的哈希 什么错误?请详细说明您的预期。 @Aybe - 是的,我调试了代码。 @NiklasB。 - 正如你所提到的,我检查了 eqaul 子字符串的哈希值。并且哈希值不匹配。根据伪代码我认为我已经正确编写了它。以下是伪代码。 i.stack.imgur.com/a5zLD.png 【参考方案1】:

我不熟悉 Rabin-Karp 算法,但我很确定你应该推进 rollingHashOf_ProllingHashOf_T

if (i < diffNM)

    rollingHashOf_T = Math.Abs(sizeOfAlphabet * (rollingHashOf_T - (int)text[i] * h) + (int)text[i + lengthOfPattern]) % moduloValue;
    rollingHashOf_P = Math.Abs(sizeOfAlphabet * (rollingHashOf_P - (int)pattern[i] * h) + (int)pattern[i + lengthOfPattern]) % moduloValue;

在 OP 在下面的评论中分享了这个伪代码之后:

很明显,以上是错误的。将其与帖子中的代码进行比较,虽然表明该错误可能在推进rollingHashOf_T 的行中,因为它说:

rollingHashOf_T = Math.Abs(sizeOfAlphabet * (rollingHashOf_T - 
  (int)text[i] * h) + (int)text[i + lengthOfPattern]) % moduloValue;

虽然伪代码建议它应该是:

rollingHashOf_T = Math.Abs(sizeOfAlphabet * (rollingHashOf_T - 
  (int)text[i + 1] * h) + (int)text[i + lengthOfPattern + 1]) % moduloValue;

【讨论】:

根据伪代码 rollingHashOf_P 在 if 语句中是不需要的。这是伪代码:i.stack.imgur.com/a5zLD.png @user1457039 你是对的,当然,它确实说text[i+1]text[i + lengthOfPattern + 1]...

以上是关于C# 中的 Rabin-Karp 算法 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Rabin-Karp算法代码中的负哈希值

PHP 中的 Rabin-Karp 算法

Rabin-Karp 算法:为啥 h=(h*d)%q

使用 Rabin-Karp 搜索字符串中的多个模式

Rabin-Karp指纹字符串查找算法

字符串 Rabin-Karp 基本数字符号