字符与文字
字符如此普遍,构成我们语言的文字在电脑以看来字符为单位是十分合理的,我们人类的任何语言都对文字赋予了丰富的内涵,处理好每一个字符是一个负责任的一流工程师应该做的。即便是简单到不能再简单的Lisp也是把一切归为几个字符,可见几个字符的重要性。
字符串,一堆又一堆的字符,使之排序构成串,字符串操作无非有四:增、删、改、查 [ 切分 ]。
字符串操作在我看来分为两类:基于比较的和基于坐标的,比较结果,和坐标位置是我们操作字符串的基准(规则)。
搜索和遍历
创造字符串,第一步就是看看它长个啥样子,遍历整个字符串便是首要目标。
程序就是在循环之中寻找目标,循环之多少决定程序之快慢,深度亦深亦浅,全在于工程师,有尺有度,有条不紊,故此Python书上。
字符串匹配算法(正文)
字符串匹配,一文一字要挨个来,有人喜从头起,有人喜欢尾始,因人而异,因时而异
本王所讲皆是从左开始按正序开始匹配,而且只是简单讲述KMP算法和暴力搜索
暴力搜索
人的一生总是从简单直接粗暴的开始,以暴制暴方便入门。要粗暴,那就要直接裸写代码强行匹配,完全不怂!
写完代码再来看以下代码的同学日后必成大器,日后必成大器,日后必成大器,重要的文字、文字、文字说三遍!
def brute_force(text,find): #暴力搜索
start = 0 # text 比较游标
sub = 0 # find 比较游标
restart = 0
while start!=len(text):
if text[start]==find[sub]:
start+=1
sub+=1
else:
restart+=1
start=restart
#text 游标从次一项开始
sub = 0 # find 游标从 头开始
if sub==len(find):
return start - sub #由于start 游标停在最后的匹配字符上,所以我们要减去搜索串find的长度
return -1
如果以上代码看不懂,我教你一个简单快速的方法看懂,鼠标右下角,立马就懂!
当你分析懂了暴力搜索的原理(我的代码怎么表达的,弄懂restart 是什么意思),你就可以很快搞懂KMP算法是个什么鬼!
简而言之,比较俩字符串,<小明不知道小敏在哪里,而晓敏知道小明知道晓敏知道小敏在哪里> 以及<晓敏>
我们一眼就可以知道 第一个分句里没有,第二个分句有<晓敏>,我们看一眼便知道整个句子,所以瞬间出答案,同样的道理,如若我们能亚索(不,压缩)字符串做到快速遍历也是搜索之良方,不过我们不采取这种方法,而是采取一个小策略我们把<晓敏>拆开,这个句子<敏>出现次数较多,如果没有<敏>这个字,我们就可以直接跳过一些距离,直接从<小明不知道小敏在哪里>中的<在>继续查找,我想大概的意思你应该懂了那么一丢丢!
在伊犁,
很明显,GB后A 和O明显不匹配,再一个字符一个字符比较<ADA>,你这样做似不似傻
,完全可以跳过其中的<ADA>跳到第二个<G>比较就可以提高效率
所以呢,我们需要机智的预先算出来<GBORGAB>中 两个G之间的距离来确定必要时跳跃几个字符!
如何计算每个字符需要的跳转位置呢!
假使<GBORGAB>是一个特别集合,使用其子集(如:G、GB、GBO等)前缀和后缀的共有元素来确定对应字符的跳转距离!共有元素组成的集合成为跳转表
代码如下:
def kmp(text,find): #经典的KMP(Knuth-Morris-Pratt)算法
match = []
prefix_list = []
suffix_list = []
#生成 "部分匹配表"
for x in xrange(1,len(find)+1): # xrange(1,10) 生成1~9的序列
str_src = find[0:x] #str_src原字符串
prefix_list = prefix(str_src)
suffix_list = suffix(str_src)
intersection_list = [tmp for tmp in prefix_list if tmp in suffix_list]
intersection_str = ''.join(intersection_list)
match.append(len(intersection_str))
print match
#比较操作
start = 0 # text 比较游标
sub = 0 # find 比较游标
restart = 0 #跳转游标
matched_char = 0 #当前已匹配字符数
while start!=len(text): #只要没有读取到text的最后一个字符就继续 读
print 'comparing '+str(start)+' and '+str(sub)
if text[start]==find[sub]:
print 'found '+str(start)+' and '+str(sub)+'is equal'
matched_char += 1
start+=1
sub+=1
else:
if matched_char == 0:
restart +=1
else:
restart+= (matched_char - match[sub-1])
matched_char = 0
start=restart
#text 游标从次一项开始
sub = 0 # find 游标从 头开始
if sub==len(find):
return start - sub #由于start 游标停在最后的匹配字符上,所以我们要减去搜索串find的长度
return -1 #为搜索到
def prefix(item_str): #获取item_str的前缀
prefix_list = []
item_str = item_str[:-1]
for x in xrange(1,len(item_str)+1):
prefix_list.insert(x,item_str[0:x])
#print 'src='+item_str
#print prefix_list
return prefix_list
def suffix(item_str):#获取item_str的后缀
suffix_list = []
item_str = item_str[0:]
for x in xrange(1,len(item_str)+1):
suffix_list.insert(x,item_str[x:])
#print 'src='+item_str
#print suffix_list
return suffix_list
慢慢读,慢慢画吧,同学
这代码应该没什么明显的Bug!
大概,就是这样,以后争取坚持下来写博客!