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
你如何计算点击总数
以下是我的想法
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
,还是只是一个示例,您希望了解一种通用算法来计算文本流中任何字符串的出现次数?