C# Rabin-Karp字符串匹配算法
我在网站的论坛上看到了Rabin Karp字符串匹配算法,我很想尝试实现它,但我想知道是否有人能告诉我为什么变量ulong Q和ulong D分别为100007和256:S? 这些价值观有什么意义C# Rabin-Karp字符串匹配算法,c#,string,algorithm,rabin-karp,C#,String,Algorithm,Rabin Karp,我在网站的论坛上看到了Rabin Karp字符串匹配算法,我很想尝试实现它,但我想知道是否有人能告诉我为什么变量ulong Q和ulong D分别为100007和256:S? 这些价值观有什么意义 static void Main(string[] args) { string A = "String that contains a pattern."; string B = "pattern"; ulong siga = 0; ulong sigb = 0;
static void Main(string[] args)
{
string A = "String that contains a pattern.";
string B = "pattern";
ulong siga = 0;
ulong sigb = 0;
ulong Q = 100007;
ulong D = 256;
for (int i = 0; i < B.Length; i++)
{
siga = (siga * D + (ulong)A[i]) % Q;
sigb = (sigb * D + (ulong)B[i]) % Q;
}
if (siga == sigb)
{
Console.WriteLine(string.Format(">>{0}<<{1}", A.Substring(0, B.Length), A.Substring(B.Length)));
return;
}
ulong pow = 1;
for (int k = 1; k <= B.Length - 1; k++)
pow = (pow * D) % Q;
for (int j = 1; j <= A.Length - B.Length; j++)
{
siga = (siga + Q - pow * (ulong)A[j - 1] % Q) % Q;
siga = (siga * D + (ulong)A[j + B.Length - 1]) % Q;
if (siga == sigb)
{
if (A.Substring(j, B.Length) == B)
{
Console.WriteLine(string.Format("{0}>>{1}<<{2}", A.Substring(0, j),
A.Substring(j, B.Length),
A.Substring(j + B.Length)));
return;
}
}
}
Console.WriteLine("Not copied!");
}
static void Main(字符串[]args)
{
string A=“包含模式的字符串。”;
字符串B=“模式”;
ulong-siga=0;
ulong-sigb=0;
ulong Q=100007;
ulong D=256;
for(int i=0;i Console.WriteLine(string.Format(“>>{0}{1}该算法使用哈希进行快速字符串比较。Q和D是编码器可能经过一点尝试和错误就得到的幻数,并为该特定算法提供了大量哈希值
您可以看到这些类型的幻数用于对许多位置进行哈希运算。下面的示例是.NET 2.0字符串类型的GetHashCode函数的反编译定义:
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public override unsafe int GetHashCode()
{
char* chrPointer = null;
int num1;
int num2;
fixed (string str = (string)this)
{
num1 = 352654597;
num2 = num1;
int* numPointer = chrPointer;
for (int i = this.Length; i > 0; i = i - 4)
{
num1 = (num1 << 5) + num1 + (num1 >> 27) ^ numPointer;
if (i <= 2)
{
break;
}
num2 = (num2 << 5) + num2 + (num2 >> 27) ^ numPointer + (void*)4;
numPointer = numPointer + (void*)8;
}
}
return num1 + num2 * 1566083941;
}
关于神奇的数字,保罗的答案很清楚
就代码而言,Rabin Karp的主要思想是在字符串的滑动部分和模式之间执行哈希比较
不能每次对整个子串计算哈希,否则计算复杂度将是二次的O(n^2)
,而不是线性的O(n)
因此,应用一个函数,例如在每次迭代中,只需要一个字符来更新子字符串的哈希值
那么,让我们来评论一下您的代码:
for (int i = 0; i < B.Length; i++)
{
siga = (siga * D + (ulong)A[i]) % Q;
sigb = (sigb * D + (ulong)B[i]) % Q;
}
if (siga == sigb)
{
Console.WriteLine(string.Format(">>{0}<<{1}", A.Substring(0, B.Length), A.Substring(B.Length)));
return;
}
^
这里是执行滚动哈希所需的计算的pow
for (int j = 1; j <= A.Length - B.Length; j++)
{
siga = (siga + Q - pow * (ulong)A[j - 1] % Q) % Q;
siga = (siga * D + (ulong)A[j + B.Length - 1]) % Q;
if (siga == sigb)
{
if (A.Substring(j, B.Length) == B)
{
Console.WriteLine(string.Format("{0}>>{1}<<{2}", A.Substring(0, j),
A.Substring(j, B.Length),
A.Substring(j + B.Length)));
return;
}
}
}
for(int j=1;j)我不熟悉这个算法。我得到了第一个for(){}
循环,它包含一个bug。如果B.Length>a.Length呢?indexooutofrangeexception
在阅读维基百科文章()后,我可以看到Q是一个“大素数”“用于对子字符串进行散列。D似乎是一个比例因子,它将每个新字符位置视为256的倍数,但这似乎假设没有字符值>=256。不过,我在这里根本不是专家。D为256实际上是将8位向左移动,以便为下一个字符腾出空间。”(尽管,这是一个以ascii为中心的视图)非常感谢您通过注释代码来帮助我。非常感谢!
ulong pow = 1;
for (int k = 1; k <= B.Length - 1; k++)
pow = (pow * D) % Q;
for (int j = 1; j <= A.Length - B.Length; j++)
{
siga = (siga + Q - pow * (ulong)A[j - 1] % Q) % Q;
siga = (siga * D + (ulong)A[j + B.Length - 1]) % Q;
if (siga == sigb)
{
if (A.Substring(j, B.Length) == B)
{
Console.WriteLine(string.Format("{0}>>{1}<<{2}", A.Substring(0, j),
A.Substring(j, B.Length),
A.Substring(j + B.Length)));
return;
}
}
}