欢迎光临散文网 会员登陆 & 注册

【ROSALIND】【练Python,学生信】39 按顺序排列不同长度的字符串

2020-01-29 15:26 作者:未琢  | 我要投稿

如果第一次阅读本系列文档请先移步阅读【ROSALIND】【练Python,学生信】00 写在前面  谢谢配合~

题目:

排列不同长度的字符串(Organizing Strings of Different Lengths)

Given: A permutation of at most 12 symbols defining an ordered alphabet A and a positive integer n (n≤4).

所给:给出不超过12个字符的集合以及一个不大于4个正整数。

Return: All strings of length at most n formed from A, ordered lexicographically. (Note: As in “Enumerating k-mers Lexicographically”, alphabet order is based on the order in which the symbols are given.).

需得:由A中字符组成的所有长度不超过n的字符串,按照A中给出的顺序进行排列。

 

测试数据

D N A

3

测试输出

D

DD

DDD

DDN

DDA

DN

DND

DNN

DNA

DA

DAD

DAN

DAA

N

ND

NDD

NDN

NDA

NN

NND

NNN

NNA

NA

NAD

NAN

NAA

A

AD

ADD

ADN

ADA

AN

AND

ANN

ANA

AA

AAD

AAN

AAA

 

背景

        在23 按字母顺序排列的K-mer中,我们已经可以对长度相同的字符串按照字符顺序进行排列。但就像字典中不会只有相同长度的单词,我们不能满足于只排列相同长度的序列。举个例子,假设我们有两个字符串s=s1s2⋯sm和 t=t1t2⋯tn,且m<n。对于t的子串t′=t[1:m],我们有如下两种情况:

        一.若s=t’,则s<Lext,因为s比t短 (即 APPLE<APPLET)。

        二.若s≠t’,如果s<Lext’,则s<Lext;若s>Lext’,则s>Lext。(即因为APPL<LexARTS,APPLET<LexARTS)

 

计算机背景

        快速排序是一种利用分治策略的排序算法。所谓分治策略是将原问题不断分解为若干相似但规模更小的问题,以递归的方式解决这些子问题,最后再将子问题的解合并为原问题的解。快速排序的基本思想是选定一个基准值,把序列分为两个部分,一部分都比基准值小,另一部分都比基准值大,再对这两个部分用相同方式进行排序,直到整个序列都有序。具体的解释可阅读这篇博文:https://www.cnblogs.com/liuyicai/p/9985769.html。

 

思路

        我把这道题分为两个部分:首先,我要用枚举的方法得到所有字符在所有所需长度的组合;第二,我要将这些组合按要求进行排序。

        第一步我们在23 按字母顺序排列的K-mer已经基本解决了,这里只稍加改动。之前的函数返回的是储存为k-mer的列表,现在只用在最后返回结果的时候把比k-mer短的那些字符串也加到列表里,最后再把1-mer(即原字符集合)也加上即可。

        第二部实际就是排序问题,我这里采用了快速排序。网上有大量快速排序的博文和代码,参考即可。要注意的是排序时对每个字符串长度的判断,按照问题中给出的两个情况分析即可。

 

代码

def perm(c1, c2, k):
   
"""进行排列的函数"""
   
i = 0
   
ls = []
   
while i < len(c1):
        j =
0
       
while j < len(c2):
            ls.append(c1[i] + c2[j])
            j +=
1
       
i += 1
   
i = 2
   
while i < k:
        i +=
1
       
ls = ls + perm(c1, ls, k - 1) # 以递归的方式得到长度不长于k的字符的排列
       
break

    return
ls


def compare(c1, c2):
   
"""比较两个字符串大小的函数"""
   
for k in range(min(len(c1), len(c2))): # 以循环的方式比较两字符串,为避免超过范围,取短字符串为界
       
if dic[c1[k]] > dic[c2[k]]: # 比较同一位的字符大小
           
return 1 # 1代表c1比c2大
       
elif dic[c1[k]] < dic[c2[k]]:
           
return 0 # 0代表c1比c2小
   
if len(c1) > len(c2): # 执行到这里说明长字符子串和短字符相同,则谁短谁小
       
return 1
    
else:
       
return 0

def partition(seq, low, high):
   
"""进行快速排序的分组函数"""

   
pivot = seq[low] # pivot是基准值,把比它小的小的放在它左边,反之放右边

   
while low < high:
       
while low < high and compare(seq[high], pivot) == 1:
            high -=
1
       
seq[low] = seq[high]
       
while low < high and compare(seq[low], pivot) == 0:
            low +=
1
       
seq[high] = seq[low]
    seq[low] = pivot

   
return  low

def quickSort(seq, low, high):
   
"""快速排序函数"""
   
if low < high:
        pi = partition(seq, low, high)
        quickSort(seq, low, pi -
1) # 采用分治策略,不断划分为子序列进行排序
       
quickSort(seq, pi + 1, high)
   
return seq


f =
open('input.txt', 'r')
lines = f.readlines()
f.close()

N =
int(lines[1])
symbols = lines[
0].replace('\n','')
symbols = symbols.split(
' ')
# symbols = [''] + symbols

dic = {} # 建立一个字典,目的是存储每个字符和其顺序的关系
n = 1
for i in symbols:
    dic[i] = n
    n +=
1


res = perm(symbols, symbols, N) # 用res接收返回的字符串
res = symbols + res # 再把1-mer加到res前
res = quickSort(res, 0, len(res) - 1) # 快速排序

f = open('output.txt', 'a')
for i in res:
    f.write(i)
    f.write(
'\n')
f.close()


【ROSALIND】【练Python,学生信】39 按顺序排列不同长度的字符串的评论 (共 条)

分享到微博请遵守国家法律