完全版
import random
def vo(mainstr,substr):#暴力对比时间
ind=0
n=0
timer=0
result=[]
while (ind <= len(mainstr) - len(substr)):
timer=timer+1
if mainstr[ind+n]==substr[n]:
n=n+1
if n==len(substr):
result.append(ind)
ind = ind + 1
n = 0
else:
ind=ind+1
n=0
print('暴力对比结果为:'+str(result))
print('暴力对比次数为:'+str(timer))
def table(substr):#自匹配表#2
t=[]
if len(substr)==1:
tt = [[0 for j in range(len(substr))] for i in range(2)]
return tt,1
else:
for i in range(1,len(substr)): #被对比的子串
ind=0
for j in range(len(substr)): #逐个对比后,记录匹配成功数
if i+j>len(substr)-1: #当主子串被匹配完,添加到表
t.append(ind)
break
else:
if substr[j]==substr[i+j]: #内循环对比成功一个,加1
ind=ind+1
else: #直到匹配失败,添加到表
t.append(ind)
break
ind=0
tt = [[0 for j in range(len(t))] for i in range(2)]
for i in range(len(t)):
if t[i]!=0:
tt[0][ind]=i
tt[1][ind]=t[i]
ind=ind+1
return tt,ind #自匹配表,t[0]为索引位置,t[0][0]为匹配数量
def next(ind,n,t,node_nums,m):#3 node_nums是t中自匹配点数量
max_ind=0
max_val=0
if n == 0:
ind = ind + 1 + m # 第一个就匹配失败,下一位
m = 0
else:
if n - 1 >= t[0][0] + 1: # 若超越第1个相似点
for i in range(node_nums): # 寻找超越点内的最大连续位置
if n - 1 >= t[0][i] + 1:
if t[1][i] > max_val:
max_val = t[1][i]
max_ind = i
else:
break
m = n - t[0][max_ind] - 1
if m == t[1][max_ind]: # 后串与表一致,所以需要请出前串
ind = ind + n - m
else:
ind = ind + n ###############
m = 0
else:
# ind = ind + n + 1 # 否则直接跳尾
# m = 0
ind = ind + n # 否则直接跳尾
m = 0
return ind,m,max_ind
def compare(mainstr,substr):#1
ind=0 #头指针,指定当前子串的头到了主串的哪
n=0 #尾指针,记录对比结果
m=0 #内指针,无需在头指针的新位置开始对比,根据前一个对比结果,指明子串内部某位置开始
t,node_nums=table(substr)
save=[]
timer = 0
while(ind<=len(mainstr)-len(substr)):#最多查找到末尾回来一点
print('当前索引ind=' + str(ind))
print('当前剩下主串为:'+mainstr[ind:])
max_ind=0
for n in range(len(substr)-m): #根据m来确定从多少开始对比
timer=timer+1
#print('已对比次数:'+str(timer)+';当前对比字符为主串的'+mainstr[ind+n+m]+'和子串的'+substr[n+m])
if mainstr[ind+n+m]==substr[n+m]:
n=n+1
else:
ind,m,max_ind=next(ind, n, t, node_nums,m) #计算下一个匹配位置
break
if n==len(substr)-m:
save.append(ind)
m = n - t[0][max_ind] - 1
if m == t[1][max_ind]:# 只有当m==表信息,需要前串亲自上场时,才需要用到m作为偏移
ind = ind + n - m
else:
ind = ind + n+1# 这里的+1曾经出现过bug,去掉1会慢一点,但不会有bug
m = 0
print('kmp对比次数为:'+str(timer))
print('主串+子串长度为:'+str(len(mainstr)+len(substr)))
return save
def rand_str(length):
str_0 = []
for i in range(length):
str_0.append(random.choice("abcde"))
return str_0
mainstr=''.join(rand_str(300))
substr=''.join(rand_str(3))
print('待查找的主串为:'+mainstr)
print('子串为:'+substr)
vo(mainstr,substr)
result=compare(mainstr,substr)
if result!=[]:
print('主串中匹配到的索引号为'+str(result))
else:
if substr in mainstr:
print('本程序出错,该匹配到的没匹配到')
else:
print('没有查找到结果')
以下为简易版,方便在线笔试快速编写
def table(substr):
t=float('inf')
if len(substr)==1:
return t,1
else:
for i in range(1,len(substr)): #被对比的子串,简易版只需一个头位置就可以加速很多
if substr[0]==substr[i]:
t=i
break
return t
def compare(mainstr,substr):
ind=0
n=0
t=table(substr)
save=[]
timer = 0
while(ind<=len(mainstr)-len(substr)):#最多查找到末尾回来一点
print('当前对比主串为:'+mainstr[ind:])
print('当前索引:'+str(ind))
max_ind = 0
max_val=0
for n in range(len(substr)):
timer=timer+1
if mainstr[ind+n]==substr[n]:
n=n+1
else:
if n==0:
ind = ind + 1 #第一个就匹配失败,下一位
break
else:
if n-1>=t+1: #若超越第1个相似点
ind = ind + t
else:
ind=ind+n+1
break
if n==len(substr):
save.append(ind)
if n - 1 >= t + 1: # 若超越第1个相似点
ind = ind + t
else:
ind = ind + n+1
print('总对比次数为:'+str(timer))
print('主串+子串长度为:'+str(len(mainstr)+len(substr)))
return save
mainstr='ABCABCABDABkkkkkk'
substr='ABCAB'
简易版显示结果:
当前对比主串为:ABCABCABDABkkkkkk
当前索引:0
当前对比主串为:ABCABDABkkkkkk
当前索引:3
当前对比主串为:ABDABkkkkkk
当前索引:6
当前对比主串为:ABkkkkkk
当前索引:9
当前对比主串为:kkkkk
当前索引:12
总对比次数为:17
主串+子串长度为:22
主串中匹配到的索引号为[0, 3]