判断句子是不是魔法咒语的算法

javaeye 上看到一个帖子讲动态规划算法的:
http://www.javaeye.com/topic/204976?page=1

其中提出了一个题目:判断句子是不是魔法咒语。
描述如下:

"话说有个魔法字典,其中记录了一些魔力单词(字符串),如果一个句子(也是字符串)可以被完全分解为若干魔力单词的拼接,那么这个句子就是一条咒语。假设 我们可以用常数时间查询魔力字典是否包含一个特定的单词,那么现在给你一个句子,让你写一个程序判断这个句子是否一条咒语。用动态规划可以解哦。"

其中跟贴的有人说到需要先列出“状态转移方程” ,我不太懂,不过觉得这个问题倒是可以用回溯法尝试一下。
代码如下:

# coding: utf-8
#
2008-8-21, Neil Chen
#
 判断一个句子是否为咒语(由魔法词组成)
#
 解法:回溯法

#  魔法词典
magic_words  =  [ ' m ' ' foo ' ' bar ' ' boo ' ' barr ' ' jac ' ' j '   ' c ' ]

#  是否为魔力单词
def  is_magic_word(word):
    
return  word  in  magic_words

#  是否为咒语
def  is_spell(sentence):
    
#  最终如能成功分割为魔法单词,则句子中会出现 n 个分隔点,
     #  现尝试用回溯法来找出这些点的位置
    split_points  =  [ 1 ]
    n 
=  len(sentence)
    
while  True:
        
#  判断最后两个分隔点之间的单词是否为魔力单词,否则将该位置增加1,继续尝试
        is_magic  =  False
        
while  split_points[ - 1 <=  n:
            
if  len(split_points)  ==   1 :
                start 
=  0
            
else :
                start 
=  split_points[ - 2 ]
            
#  得到最后两个分隔点之间的单词
            word  =  sentence[start : split_points[ - 1 ]]            
            
if  is_magic_word(word):
                is_magic 
=  True
                
break
            
else :                
                split_points[
- 1 +=   1

        
#  最后一个分隔点之前都是魔力单词
         if  is_magic:
            
#  已经到达末尾,成功了
             if  split_points[ - 1 ==  n:
                
return  True
            
#  增加下一个分隔点位置,继续分割
             else :
                split_points.append(split_points[
- 1 +   1 )
        
#  最后一个分隔点无论怎样选都不能组成一个魔力单词,则需要回溯到上一个分隔点
         else :
            
#  退无可退!表示这个句子不是咒语
             if  len(split_points)  ==   1 :
                
return  False
            
#  退回到上一个分隔点
             else :
                split_points.pop()
                
#  将回溯到的位置加一,重新进入下一次循环尝试
                split_points[ - 1 +=   1


# ================ 测试代码 ======================
if   __name__   ==   ' __main__ ' :
    
print  is_magic_word( ' foo ' )           #  True
     print  is_magic_word( ' fo ' )            #  False

    
print  is_spell( ' morning ' )            #  False
     print  is_spell( ' hello ' )              #  False
     print  is_spell( ' foo ' )                #  True
     print  is_spell( ' bar ' )                #  True
     print  is_spell( ' barfoombarmjac ' )     #  True


以上代码已经实现了这个算法。(不过有个小小的问题,如果字符串里含有中文,则不能正确判断,这是因为 python 中 len() 函数判断中文为双字节造成的,等有时间再改进这个)。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值