总结|最长的指定瑕疵度的字符子串

题目描述:

开头和结尾都是元音字母(aeiouAEIOU)的字符串为元音字符串,其中混杂的非元音字母数量为其瑕疵度。 

“a” 、“aa”是元音字符串,其瑕疵度都为 0
“aiur”不是元音字符串(结尾不是元音字符)
“abira”是元音字符串,其瑕疵度为 2
给定一个字符串,请找出指定瑕疵度的最长元音字符子串,并输出其长度,如果找不到满足条件的元音字符子串,输出 0。
 

flaw=int(input())
s=input()

#不重复选择set
vowels=set('aeiouAEIOU')

n=[]
for i in range(len(s)):
        if s[i] in vowels:
            #n记录s中是元音字符的位置,作为新的数组
            n.append(i)
l,r=0,0
length=[]
#r作为数组的序号,不能=n的长度,否则列表超限
while r<len(n):
    #lengthdiff记录s中两个元音之间的间隔个数,也就是这里的瑕疵数
    #n[r]-n[l]表示在n数组里,左右指针分别对应s中的元音字符的序号
    #如果左右指针相邻,则间隔数=序号差-1;
    #但是左右指针的位置会移动,左右指针的移动数=r-l;左右指针指向同一个字符,则此移动数=0
    #所以间隔数=序号差-左右指针的移动数=n[r]-n[l]-(r-l)
    lengthdiff=n[r]-n[l]-(r-l)
    #大于瑕疵数了,l往后走,寻找下一个等于瑕疵数的子串
    if lengthdiff>flaw:
        l+=1
    else:
        if lengthdiff==flaw:
            length.append(n[r]-n[l]+1)
        r+=1

if len(length)==0:
    print(0)
else:
    print(max(length))

这道题最难理解的地方在于计算瑕疵度:

lengthdiff=n[r]-n[l]-(r-l)

通过厚德载物这位博主的讲解,具体操作过程如下图:

输入:

0
asdbuidevauufgh

在输入字符串中,属于元音字符的序号是:0、4、5、6、8、10、11、12

蓝色箭头表示左指针,另一个颜色表示右指针

计算瑕疵数可以理解为计算两个元音之间的间隔

n[r]、n[l] 表示左、右指针指向新列表中元音的序号

n[r]-n[l] 在图中表示:

0-0a→a
4-0u→a
5-4i→u
6-4o→u

从表格很直观看出:

1、指向同一个元音,瑕疵数=0(这里的瑕疵数至少是两个元音以上讨论)

2、不相邻的元音(指在输入字符串中不相邻,即图中方块里的序号不连续),瑕疵数=3

3、相邻的元音,瑕疵数=0

4、连续相邻的元音,瑕疵数=0

但是n[r]-n[l]只是表示了下一个元音到上一个元音在输入字符串中的移动步数

r-l 表示右指针到左指针在新组成的元音列表中的移动步数

若两个指针指向同一个元音序号,则 r-l=0

若两个指针指向相邻元音序号,则 r-l=1

所以,两个指针指向不同元音序号,则 r-l=元音间的移动步数

所以,瑕疵数=两个元音之间的间隔=非元音个数=两个元音在输入字符串中的移动步数(包括了非元音和元音)-元音间的移动步数(只有元音)

移动步数+1=个数

所以,上式也可理解为:

瑕疵数=左右指针指向的非元音个数=左右指针指向的全部字符个数-左右指针指向的元音字符个数={两个元音在输入字符串中的移动步数(包括了非元音和元音)+1}-{元音间的移动步数(只有元音)+1}

然后,计算的瑕疵数与给定的瑕疵数进行比较。一共有三种情况:

lengthdiff>flaw,l++
lengthdiff==flaw,r++
lengthdiff<flaw,r++

最后,输出指定瑕疵度lengthdiff==flaw的最长元音字符子串的长度=max(列表中,下一个元音到上一个元音在输入字符串中的移动步数+1)=max(列表中,n[r]-n[l]+1)

在这里用 n[r]-n[l] 或 r-l 是同样的,因为最长元音字符子串是连续的,无论是输入子串中的连续(如图中,6-4,12-10),还是新列表中的连续(3-1,7-5)表示的都是从字符o-u,u-a

这里的长度还+1,是移动步数为2,则个数就为3;移动步数为n,则个数就为n+1

  • 23
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值