String 滑动窗口中的字符串匹配

String 滑动窗口中的字符串匹配,string,algorithm,pattern-matching,trie,String,Algorithm,Pattern Matching,Trie,假设您有一个包含以下字符串的文件 a a a b a a b a a b b a b 您没有访问该文件的权限,但有一个函数FetchNextChar(),它一次提供一个字符 要匹配的模式是a a b 你如何计算点击总数 以下是我的想法 如果获取的字符是模式('a')的第一个字符,则将其添加到队列中 如果下一个字符与模式的下一个字符匹配,则开始追加/创建下一个字符的链接列表 所以在第一次取货之后我们有 Pattern -a Queue - a Then Pattern -a a

假设您有一个包含以下字符串的文件

a a a b a a b a a b b a b 
您没有访问该文件的权限,但有一个函数FetchNextChar(),它一次提供一个字符

要匹配的模式是
a a b

你如何计算点击总数

以下是我的想法

  • 如果获取的字符是模式('a')的第一个字符,则将其添加到队列中
  • 如果下一个字符与模式的下一个字符匹配,则开始追加/创建下一个字符的链接列表
  • 所以在第一次取货之后我们有

    Pattern -a 
    Queue - a 
    
    Then 
    
    Pattern -a  a 
    Queue[0] a->a 
    Queue[1] a
    
    
    3rd 
    Pattern    a    a    b
    Queue[0]   a -->a--> a    //doesn't match, dequeue
    Queue[1]        a-> a
    Queue[2]             a 
    
    我认为这会起作用,但我看到的问题是,是否有多个字符与模式的第一个字符相匹配,我将继续添加到队列中,从而不断增加列表


    有什么想法吗?

    您可以使用基于状态的算法:

    我们可以看到,每次读取a
    'b'
    时,我们都会继续执行
    状态=0
    ,如果启用
    状态=2
    ,则模式出现的次数会增加一次。当一个
    'a'
    被读取时,我们进入下一个状态,该状态的边界显然是
    状态=2

    这里是一个实现该算法的python脚本


    您可以使用基于状态的算法:

    我们可以看到,每次读取a
    'b'
    时,我们都会继续执行
    状态=0
    ,如果启用
    状态=2
    ,则模式出现的次数会增加一次。当一个
    'a'
    被读取时,我们进入下一个状态,该状态的边界显然是
    状态=2

    这里是一个实现该算法的python脚本


    通过计算滑动窗口的
    滚动哈希
    可以有效地解决这一问题,简单的滚动哈希函数是对字符的ASCII码求和,但您可以使用此
    素数数组
    减少冲突,我已经测试了这些素数,并在一个大而相似的字符串和模式匹配上给了我一些碰撞:

    primes[] = {13 , 7963 , 17443 , 27527 , 37879 , 48673 , 59407 , 70729 , 81883 , 93251 , 104789 , 116531 , 128239 , 139969 , 151783 , 163883 , 176159 , 188029 , 200257 , 212447 , 224831 , 237283 , 249517 , 262217 , 274661 , 287173};
    
    下面是用于打印匹配计数的上述算法的伪代码:

    stream = "aaabaabaabbab";
    pattern = "aab";
    queue window;
    
    patternHash = 0;
    for ch in pattern:
        patternHash = patternHash + primes[ch - 'a']
    
    first = readFromStream(stream)
    window.enqueue(first)
    windowHash = primes[first - 'a']
    for i = 0 to pattern.size():
        ch = readFromStream(stream)
        window.enqueue(ch)
        windowHash = windowHash + primes[ch - 'a']
    
    count = 0
    for i = pattern.size() to stream.size():
        if windowHash == patternHash
            if window == pattern
                count = count + 1
        ch = readFromStream(stream)
        window.enqueue(ch)
        windowHash = windowHash - primes[window.first() - 'a']
        windowHash = windowHash + primes[ch - 'a']
        window.dequeue()
    
    print count
    

    通过计算滑动窗口的
    滚动哈希
    可以有效地解决这一问题,简单的滚动哈希函数是对字符的ASCII码求和,但您可以使用此
    素数数组
    减少冲突,我已经测试了这些素数,并在一个大而相似的字符串和模式匹配上给了我一些碰撞:

    primes[] = {13 , 7963 , 17443 , 27527 , 37879 , 48673 , 59407 , 70729 , 81883 , 93251 , 104789 , 116531 , 128239 , 139969 , 151783 , 163883 , 176159 , 188029 , 200257 , 212447 , 224831 , 237283 , 249517 , 262217 , 274661 , 287173};
    
    下面是用于打印匹配计数的上述算法的伪代码:

    stream = "aaabaabaabbab";
    pattern = "aab";
    queue window;
    
    patternHash = 0;
    for ch in pattern:
        patternHash = patternHash + primes[ch - 'a']
    
    first = readFromStream(stream)
    window.enqueue(first)
    windowHash = primes[first - 'a']
    for i = 0 to pattern.size():
        ch = readFromStream(stream)
        window.enqueue(ch)
        windowHash = windowHash + primes[ch - 'a']
    
    count = 0
    for i = pattern.size() to stream.size():
        if windowHash == patternHash
            if window == pattern
                count = count + 1
        ch = readFromStream(stream)
        window.enqueue(ch)
        windowHash = windowHash - primes[window.first() - 'a']
        windowHash = windowHash + primes[ch - 'a']
        window.dequeue()
    
    print count
    

    为什么不使用KMP算法呢?@Imposter如果你想提的话,可以这样做。这是一个已解决的问题。参见Gusfield 1997。从实用的角度来看,最好的算法是Boyer-Moore算法。什么样的DS能够有效地存储文件中的文本并滑动窗口?理想情况下,我们只希望在缓冲区中存储模式的长度以进行比较。您希望只匹配
    aab
    ,还是只是一个示例,你想知道一个通用算法来计算文本流中任何字符串的出现次数吗?为什么不使用KMP算法呢?@Imposter,如果你想提及它的话。这是一个解决了的问题。参见Gusfield 1997。从实用的角度来看,最好的算法是Boyer-Moore算法。什么样的DS能够有效地存储文件中的文本并滑动窗口?理想情况下,我们只希望将模式的长度存储在缓冲区中进行比较。您希望只匹配
    aab
    ,还是只是一个示例,您希望了解一种通用算法来计算文本流中任何字符串的出现次数?