鱼C论坛

 找回密码
 立即注册
查看: 89|回复: 4

这行代码中的 s.startswith(s[i:i*2])是不是多余了呀?

[复制链接]
发表于 6 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在字符串3的作业(编写一个程序,判断输入的字符串是否由多个子字符串重复多次构成)的最后一题答案中, s.startswith(s[i:i*2])这行代码好像不需要写也可以实现要求,是不是多余了呀?

s = input("请输入一个由字母构成的字符串:")
   
n = len(s)
for i in range(1, n//2+1):
    # 如果子字符串的长度为i,则n必须可以被i整除才行
    if n % i == 0:
        # 如果子字符串的长度为i,则i到i*2之间是一个重复的子字符串
        if s.startswith(s[i:i*2]) and s.count(s[i:i*2]) == n/i:
            print(True)
            break
# for...else的用法,小甲鱼希望大家还没有忘记哦^o^
else:
    print(False)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 6 天前 | 显示全部楼层
是的,你观察得很仔细!在代码中,s.startswith(s) 确实是多余的,因为它总是返回 True。任何字符串都以自身开头,所以这个条件不会影响程序的逻辑。

然而,代码中还有一个更严重的问题:s.count(s) == n/i 这部分可能不是意图的实现方式。s.count(s) 计算的是整个字符串 s 在自身中出现的次数,这总是 1(除非字符串为空)。因此,对于大多数情况,这个条件永远不会成立,导致程序可能无法正确判断字符串是否由重复子字符串构成。

正确的实现应该检查子字符串的重复。例如,可以这样写:


  1. s = input("请输入一个由字母构成的字符串:")
  2. n = len(s)
  3. for i in range(1, n//2 + 1):
  4.     if n % i == 0:
  5.         substring = s[:i]  # 获取可能的重复子字符串
  6.         if s == substring * (n // i):  # 检查整个字符串是否由子字符串重复构成
  7.             print(True)
  8.             break
  9. else:
  10.     print(False)
复制代码


在这个修正后的代码中,我们直接比较字符串是否等于子字符串的重复,这样就避免了多余和不正确的条件。希望这能帮助你更好地理解!如果还有其他问题,欢迎继续问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层
FishC 发表于 2025-8-21 16:17
是的,你观察得很仔细!在代码中,s.startswith(s) 确实是多余的,因为它总是返回 True。任何字符串都以自 ...

这个作业的要求是输入一个由多个重复的子字符串组成的字符串要返回true其他情况返回False,如输入:"FCFC"输出:True,输入:"fcffcffvf"输出:False.
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
WENZH 发表于 2025-08-21 16:23
FishC 发表于 2025-8-21 16:17
是的,你观察得很仔细 ...


是的,你指出的非常正确!在原始代码中,s.startswith(s) 确实是多余的,因为它总是返回 True(任何字符串都以自身开头)。更重要的是,s.count(s) == n/i 这部分逻辑是错误的,因为 s.count(s) 总是返回 1,导致条件无法正确判断重复子字符串。

正确的实现应该直接检查字符串是否由子字符串重复构成。以下是修正后的代码:


  1. s = input("请输入一个由字母构成的字符串:")
  2. n = len(s)
  3. for i in range(1, n//2 + 1):
  4.     if n % i == 0:
  5.         substring = s[:i]  # 获取可能的重复子字符串
  6.         if s == substring * (n // i):  # 检查整个字符串是否由子字符串重复构成
  7.             print(True)
  8.             break
  9. else:
  10.     print(False)
复制代码


这个代码会正确工作:
- 对于输入 "FCFC",它会输出 True,因为它是 "FC" 重复两次。
- 对于输入 "fcffcffvf",它会输出 False,因为没有重复子字符串。

感谢你的细心观察!如果还有其他问题,欢迎继续讨论。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 5 天前 | 显示全部楼层
基本是多余的!

在已满足 n % i == 0 的前提下,设候选模式 p = s[i:i*2],如果 s.count(p) == n//i,说明在长度为 n 的字符串里,有 恰好 n//i 个互不重叠、长度为 i 的 p。这些片段总长度是 i * (n//i) = n,因此它们必须把整串从头到尾“铺满”。

要想铺满且不越界,最左边那个必然从下标 0 开始,后面只能出现在 i, 2i, 3i, …。

所以这时自然有 s.startswith(p),也就是 s[:i] == s[i:i*2]。

因此 startswith 判断在这个逻辑下确实是冗余的。


一些小建议(优化代码)

用整数除法更合适:n//i(/ 在Python3里是浮点除法)。

直接用开头那段作为模式更直观,也避免读者困惑:p = s[:i]。

这样写既清晰也等价,且无须 count 的微妙语义:

  1. s = input("请输入一个由字母构成的字符串:")
  2. n = len(s)

  3. for i in range(1, n // 2 + 1):
  4.     if n % i == 0:
  5.         p = s[:i]
  6.         if p * (n // i) == s:
  7.             print(True)
  8.             break
  9. else:
  10.     print(False)
复制代码

再送两个常见的一行/线性时间写法(了解即可):

  • 经典拼接技巧:print(s in (s + s)[1:-1])(判断是否由某个子串重复且至少两次)。
  • KMP前缀函数法(O(n)):求 lps,若 n % (n - lps[-1]) == 0 且 lps[-1] > 0 则为真。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-8-27 03:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表