Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/200.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
Rabin-Karp算法的PHP实现_Php_String_Algorithm_Hash_Rabin Karp - Fatal编程技术网

Rabin-Karp算法的PHP实现

Rabin-Karp算法的PHP实现,php,string,algorithm,hash,rabin-karp,Php,String,Algorithm,Hash,Rabin Karp,嗨,我正在编写一个PHP类来实现Rabin-Karp算法。我对重新散列部分有异议。此代码不包括匹配的部分字符。我不得不停止,因为它从来没有匹配的哈希代码,因为重新哈希的问题。谁来帮我弄清楚 <?php class RabinKarp { /** * @var String */ private $pattern ; private $patternHash ; private $text ; private $previous

嗨,我正在编写一个PHP类来实现Rabin-Karp算法。我对重新散列部分有异议。此代码不包括匹配的部分字符。我不得不停止,因为它从来没有匹配的哈希代码,因为重新哈希的问题。谁来帮我弄清楚

<?php
 class RabinKarp
 {
    /** 
    * @var String
    */ 
    private $pattern ;
    private $patternHash ;
    private $text ;
    private $previousHash ;

    /** 
    * @var Integer
    */ 
    private $radix ;
    private $prime ;
    private $position ;

    /** 
    * Constructor 
    *
    * @param String $pattern - The pattern
    *
    */ 
    public function __construct($pattern) 
    {
        $this->pattern = $pattern;
        $this->radix = 256;
        $this->prime = 100007;
        $this->previousHash = "";
        $this->position = 0;
        $this->patternHash = $this->generateHash($pattern);
    }

    private function generateHash($key)
    {
        $charArray = str_split($key);
        $hash = 0;
        foreach($charArray as $char)
        {
             $hash = ($this->radix * $hash + ord($char)) % $this->prime;
        }

        return $hash;
    }

    public function search($character)
    {
        $this->text .= $character;
        if(strlen($this->text) < strlen($this->pattern))
        {
            return false;
        }
        else
        {
            $txtHash = 0;
            echo $this->previousHash . "<br/>";
            if(empty($this->previousHash))
            {
                $txtHash = $this->generateHash($this->text);
                $this->previousHash = $txtHash;
                $this->position = 0;
            }
            else
            {
                // The issue is here 
                $charArray = str_split($this->text);
                $txtHash = (($txtHash  + $this->prime) - $this->radix * strlen($this->pattern) * ord($charArray[$this->position]) % $this->prime) % $this->prime;
                $txtHash = ($txtHash * $this->radix + ord($character)) % $this->prime; 

                $this->previousHash = $txtHash;
            }

            if($txtHash == $this->patternHash)
            {
                echo "Hash Match found";
            }
        }

    }

 }

$x = new RabinKarp("ABC");
$x->search("Z");
$x->search("A");
$x->search("B");
$x->search("C");
?>


谢谢。

您要删除的字符(
c
表示简短)对哈希值的贡献是

ord(c) * radix^(length(pattern)-1)
由于字符在第一次进入匹配窗口时贡献了
ord(c)
,因此哈希值(因此也是其贡献值)与进入匹配窗口的每个
长度(模式)-1
字符的
radix
相乘,直到
c
最后离开

但是你要减去
ord(c)*基数*长度(模式)

此外,在计算中使用变量
$txtHash
,该变量已设置为0,应为
$this->previousHash
,并且必须增加文本位置

原则上,

$charArray = str_split($this->text);
$txtHash = (($this->previousHash  + $this->prime)
             - pow($this->radix, strlen($this->pattern)-1)
             * ord($charArray[$this->position]) % $this->prime)
           % $this->prime;
$txtHash = ($txtHash * $this->radix + ord($character)) % $this->prime;

$this->previousHash = $txtHash;
$this->position += 1;
这是你必须做的

但是除非模式很短,
pow($this->radix,strlen($this->pattern)-1)
将溢出,因此您必须用模幂函数替换
pow($this radix,strlen($this->pattern)-1)

function mod_pow($base,$exponent,$modulus)
{
    $aux = 1;
    while($exponent > 0) {
        if ($exponent % 2 == 1) {
            $aux = ($aux * $base) % $modulus;
        }
        $base = ($base * $base) % $modulus;
        $exponent = $exponent/2;
    }
    return $aux;
}
(如果此处的
$modules
(即
$this->prime
)太大,仍可能溢出)。相关代码行变为

$txtHash = (($this->previousHash  + $this->prime)
             - mod_pow($this->radix, strlen($this->pattern)-1, $this->prime)
             * ord($charArray[$this->position]) % $this->prime)
           % $this->prime;
那么你就有一个潜在的巨大的低效率

$this->text .= $character;
...
    $charArray = str_split($this->text);

如果字符串变长,连接和拆分可能需要很多时间(不确定PHP如何实现字符串和字符串操作,但它们可能不是固定时间)。您可能应该只保留字符串的相关部分,即在重新计算哈希后删除第一个字符。

此算法是否适用于多字节字符串值?如果是这样的话,您可能应该使用
mb
函数来计算长度。这个算法是为串行传输而编写的。假设您一次按顺序获得一个字符。一旦我收到字符,我就开始搜索。上面的代码对我来说很好。唯一的问题是在重新散列部分。实际上,重新散列的值是不正确的。@PrasadRajapaksha嗨,Prasad先生。。请你把固定密码寄出去好吗。我正在寻找用php实现多模式的rabin-karp算法。请提前谢谢。非常感谢你的回答。然而,它仍然表示哈希不匹配。也许我被误解了。如果您能用您的答案修改搜索功能,我将不胜感激。在我的例子中,ABC与模式匹配。非常感谢你的帮助。
$this->text .= $character;
...
    $charArray = str_split($this->text);