自然语言处理当中常用的算法
分而治之:
1、分成两半分给另外两个人来排序,他们又可以做同样的事情
2、得到两个排序号的卡片堆,合并成单一的排序堆
递归
在这里用一个例子来说明递归、构建一个字母查找树。
def
insert(trie,key,value): if
key: fist,rest=key[0],key[1
:] if fist not in
trie: trie[first]=
{} insert(trie[first],rest,value) else
: trie['value']=
value >>>trie =
nltk.defaultdict(dict) >>>insert(trie, 'chat', 'cat'
) >>>insert(trie, 'chien', 'dog'
) >>>insert(trie, 'chair', 'flesh'
) >>>insert(trie, 'chic', 'stylish'
) >>>trie = dict(trie) #for nicerprinting >>>trie['c']['h']['a']['t']['value'
] 'cat' >>>
pprint.pprint(trie) {'c': {'h':{'a': {'t': {'value': 'cat'
}}, {'i': {'r': {'value': 'flesh'
}}}, 'i': {'e': {'n':{'value': 'dog'
}}} {'c': {'value': 'stylish'}}}}}
动态规划
动态规划用于解决包含多个重叠的子问题的问题,不是反复计算这些子问题,而是简单的将他们的计算结果存储在一个查找表中。
问题背景:S占一个音节,L占2个音节。如果想要构造4个音节的旋律,有这样几种情况。
V4={LL,SSL,SLS,LSS,SSSS}
可以再次把这个集合分成两种:
1、一种是以L为开始的子集:LL,LSS
2、以S为开始的子集:SSL,SLS,SSSS
依次递归往下分。
V4 =
LL,LSS
i.e. Lprefixed to eachitem of V2 = {L, SS}
SSL,SLS,SSSS
i.e. S prefixed to each item ofV3 = {SL,LS,SSS}
这里有四种方法,计算旋律
1、
def virahanka1(n): if n==0: return [""] elif n==1: return ["S"] else: s = ["S" + prosody for prosody in virahanka1(n-1)] l = ["L" + prosody for prosody in virahanka1(n-2)] return s + l
2、
def virahanka2(n): lookup = [[""], ["S"]] for i in range(n-1): s = ["S" + prosodyfor prosody in lookup[i+1]] l = ["L" + prosodyfor prosody in lookup[i]] lookup.append(s + l) return lookup[n]
3、
def virahanka3(n,lookup={0:[""], 1:["S"]}): if n not in lookup: s = ["S" + prosody for prosody in virahanka3(n-1)] l = ["L" + prosody for prosody in virahanka3(n-2)] lookup[n] = s +l return lookup[n]
4、
from nltk import memoize @memoize def virahanka4(n): if n==0: return [""] elif n==1: return ["S"] else: s = ["S" + prosody for prosody in virahanka4(n-1)] l = ["L" + prosody for prosody in virahanka4(n-2)] return s + l
程序运行的效果:
>>>virahanka1(4) ['SSSS', 'SSL', 'SLS', 'LSS', 'LL'] >>>virahanka2(4) ['SSSS', 'SSL', 'SLS', 'LSS', 'LL'] >>>virahanka3(4) ['SSSS', 'SSL', 'SLS', 'LSS', 'LL'] >>>virahanka4(4) ['SSSS', 'SSL', 'SLS', 'LSS', 'LL']