前缀表
基础知识
前缀表:模式串除了最后一个字符的所有子串(但必须从第一个开始),以及他们对应的最长相等前后缀
后缀表:模式串除了第一个字符的所有子串(从后往前,从最后一个开始)
最长相等前后缀:在最前和最后完全相同的子串
开始匹配的位置就是前缀表最大数对应的字符串的索引位置。
next数组有三种方式,第一种是正常的状态,第一是整体右移动,左边第一位填充-1,第二种是所有内容-1
第一种方式时,如果发生了冲突,就找发生冲突的前一位next表中的索引位置,第二种方式则找冲突位置对应的索引即可,第三种是找到前一位再加一。
next数组的四个步骤,初始化,前后缀不相同,前后缀相同,next。
初始化:i 后缀末尾,j前缀末尾,因为要找的就是最大相等的前后缀,那么j初始化成0,next初始化为[0],因为第一个位置肯定是0,例如a,他没有与之相等的后缀,也不可能会有,那么next表第一位一定是0,之后 i 就从1开始,因为i=0的时候时没有后缀的!!,i最大应该是模式串的最右边。
找不相等:不相等的情况就应该是尾部不相同,那j就要开始回退查找,j应该回退的位置下标就是它前一位所对应的next数字,也要不停的回退,直到找到相等的,或者是j到了尽头为0了
找到相等:如果此时i和j对应的元素是相等的,那么就可以先进行j+1,因为j是索引,+1之后才是最大相等前后缀的长度。next[i]之后就应该等于j,next[i]=j的含义是,包括i位置的字符串中,最大相等的前后缀的长度。
关于i和j的位置,我的个人理解是,每次起始的时候,j所指向的位置表示着先前有没有相等的前后缀,j为0,那么就说明在上一个轮次中,没有找到相等的前后缀,那如果j不为0,那么我们就要从j的位置继续找相等的前后缀,起到一个叠加的效果
28. 实现 strStr()
题目描述: 28. 实现 strStr().
解法
不减1的前缀表
class Solution(object):
def strStr(self, haystack, needle):
def init_next(needle):
j = 0
nextL = [0]*len(needle)
for i in range(1,len(needle)):
while j>0 and needle[i] != needle[j]:
j = nextL[j-1]
if needle[i] == needle[j]:
j = j + 1 # j会先到下一个进行对比的地方,+1之后也正好是最大的前后缀相同长度
nextL[i] = j
return nextL
nextL = init_next(needle)
j = 0
if not needle:
return 0
for i in range(len(haystack)):
while j > 0 and haystack[i] != needle[j]:
j = nextL[j-1]
if haystack[i] == needle[j]:
j += 1
if j == len(needle):
return i - len(needle) + 1
return -1
首先是构建模式串的前缀表,这个表是主串用来查询的。
建立好表格之后,就开始在主串进行遍历,一直进行匹配,如果匹配不到了,就找距离最近的能和当前串匹配的模式串的子串,实际上就是主串削减了前一部分的串,而模式串削减了后一部分的串,这个串和模式串的前一部分是重合的,那么在主串中就可以不用从模式串的开头查找了,因为主串中已经有一部分是和削减之前的模式串的后一部分相同,也与削减后的模式串的前一部分相同,那如果没有相同的部分,就要在主串中,从模式串的头开始查找与模式串对应的部分了。那最后如果在模式串中的指针没有走到最后,那就意味着模式串没能完整的遍历完,也就是没有完整匹配。就要返回-1,如果j此时超出子串的长度,那么i此时对应的已经是模式串的最后一位了,那第一个匹配好的模式串的开头索引就应该是 i - 模式串长度 + 1。