编程珠玑第6章

习题6.2: (a) 大整数分解:假设需要多次计算大整数分解因子。首先可以利用筛法计算出一部分较小素数(2-m),然后存储起来。然后利用这些素数对大整数进行分解,将大整数变成一个相对较小的数。然后继续利用筛法和已有的素数计算新的素数序列(m-km),不断重复上面的过程,直到该数自己小于下一个素数。伪代码如下:

compute the base_primes
def f(n,primes)
    for each in base_primes:
        while  1:
            t =n/each
            if t is not integer:break
            output each
            n = t# update t
        if n < each:
            output n#n is the last prime
            return
    compute the next_primes and add it to base_primes

        f(n,nextprimes)#call the function recursively using new base_primes and new n

代码如下:

#compute the base_primes
base_primes = [2,3,5,7,11,13,17,19]
def test(f,randargs,case=10):
    import time,random
    start = time.time()
    for i in range(case):
        f(randargs())
    end = time.time()
    print(end-start)
def compute_primes(k = 1.5):
    global base_primes
    next_primes = list(range(base_primes[-1]+2,int(k*(base_primes[-1])),2))
    for each in base_primes:
        temp = []
        for it in next_primes:
            if it%each!=0 :temp.append(it)
        next_primes = temp
    if next_primes==[]:return []
    next_prime = min(next_primes)
    ans = [next_prime]
    base_primes.append(next_prime)
    for each in ans:
        temp=[]
        for it in next_primes:
            if it%each!=0:temp.append(it)
        if temp==[]:break
        next_primes = temp
        m = min(next_primes)
        ans.append(m)
        base_primes.append(m)
    return ans
def f(n,primes = base_primes):
    for each in primes:
        while 1 :
            if n%each!=0:break
            #print(each)
            n //=each # update t
        if n < each:
            if n != 1:print(n)#n is the last prime
            #print('*'*10)
            return
    #compute the next_primes and add it to base_primes
    x = min(int(primes[-1]*1.5),n)
    #if x-primes[-1] < 1000:
    f(n,compute_primes(x))#call the function recursively using new base_primes and new n
    #else:
    #   direct_func(n,primes[-1]+2)
import random
test(f,lambda:random.randint(2**10,2**17),case=50)

该方法的瓶颈在于计算新的素数序列消耗太大。存储已有的素数序列可以在大整数比较多的时候起到加速作用。但是这种方法对于提高计算单个case是没有帮助的,用普通的办法肯定不能计算500位。pollard-rho质数分解算法可以帮助我们,但是具体的实现我就没有去做了,这只是提供了算法层面上提高速度的思路。

另外使用test函数来辅助测试耗时。

(b) 查找字符串:

首先从算法层面采取KMP算法,伪代码如下:
def compute_matches:
    pass
def match(str,text):
    str_len = len(str)
    text_len = len(text)
    pos = 0
    while pos+str_len<=text_len:
        test if str mathces text from pos
            length = the length of matching substr
        if success:return pos
        else pos += matches[length]
    return -1

具体实现见该博文:
http://blog.youkuaiyun.com/pp634077956/article/details/51864103

除此之外,还可以考虑问题的输入,这从问题的定义入手,假如查找的是文章里面的某一个单词或者句子,那么可以提前预处理每一个单词,对它们散列化并存储每一个单词的位置序列,然后再直接跳转到首单词存在的位置进行比较,这样效率很高,但是空间消耗也非常大!当然要这样只能对单词进行处理,如果要查某一个单词的一部分就无能为力了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值