子字符串的判断与位置确定,KMP算法的理解
给定字符串 s 和 t , s 是否为 t 的子字符串,若是则给出s在t中的首项位置。
例:t=BBC_ABCDAB_ABCDABCDABDE
S=ABCDABD 长度为7(例如,"bcd"是"abcde"的一个子字符串,而"aec"不是)
这个问题可以直接暴力解决,先从t[0]开始挨个比较s,然后在从t[1]…开始。
第二种解法是KMP算法:
在理解这个算法时遇到了些困难,在这里自己在梳理一下,
算法基本思想是从t[q]开始依次和s比较,假设s长度为ns,然后发现 t[q]-t[k+q-1]=s[0]-s[k-1];(其中k<ns);
就好比下面这个例子:
BBC_ABCDAB_ABCDABCDABDEABCDABD
这时s[0]–s[5]都已在t中找到匹配项,但s[6]确和t中的下一位不相同,按照暴力解法,这时我们从本次比较中t的起始点往后顺移一位作起始点,然后在依次比较过去。
但我们发现(假设本次比较t从t[r]开始)我们已知t[r]-t[k+r-1]=s[0]-s[k-1] ,也就是说此时我们已经知道t[r+1]-t[k+r-1]=s[1]-s[k-1];暴力解法从t[r+1]开始,依次和s比较,如果比较成功,则说明t[r+1]-t[k+r-1]=s[0]-s[k-2];再结合t[r+1]-t[k+r-1]=s[1]-s[k-1],则必有s[1]-s[k-1]=s[0]-s[k-2],反之也就是说如若s[1]-s[k-1]=s[0]-s[k-2]不成立,则t从t[r+1]开始必不成功。问题也就转化为在已经匹配成功的s[0]-s[k-1]中,寻找一个下标h其中(h<k-1),使得s[0]-s[h]=s[k-h-1]-s[k-1],然后s从s[h+1]开始,t从t[k+r]开始接着依次比较是否和s相同,这样就避免了对t的无用的重复的讨论。但这里就有一个问题是如何找到这个h使得在S[0]-s[k-1]中s[0]-s[h]=s[k-h-1]-s[k-1],也就是转化为在一个字符数组中寻找个下标使得“头尾重合”。先假设有这么一个函数Find(形参为字符串数组),也就是kmp中的fail函数(手动滑稽)。那么这个问题代码为:
int Kfind(string s, string t) {
int ns = s.size();