Python 如何计算将给定字符串拆分为素数的方法数?

Python 如何计算将给定字符串拆分为素数的方法数?,python,data-structures,Python,Data Structures,我有一个问题,如下所述,将一个字符串拆分为多个显示素数的组合方式。但我不知道如何开始编码。我不能从任何逻辑开始 给定由数字[0-9]组成的长度为n的字符串,计算 给定字符串可以拆分为素数的方式的数量,每个 其范围为2至100(含)。因为答案是可以的 大,返回模109+7的答案。注意:一个分区 包含前导零的数字将无效,且初始值 字符串不包含前导零。以输入为例 字符串为s=11373,则此字符串可拆分为6 不同的方式如[11,37,3,113,7,3,11,3,73,11,37,3, 113、73和

我有一个问题,如下所述,将一个字符串拆分为多个显示素数的组合方式。但我不知道如何开始编码。我不能从任何逻辑开始

给定由数字[0-9]组成的长度为n的字符串,计算 给定字符串可以拆分为素数的方式的数量,每个 其范围为2至100(含)。因为答案是可以的 大,返回模109+7的答案。注意:一个分区 包含前导零的数字将无效,且初始值 字符串不包含前导零。以输入为例 字符串为s=11373,则此字符串可拆分为6 不同的方式如[11,37,3,113,7,3,11,3,73,11,37,3, 113、73和[11373],其中每一个都只包含素数 数字

自定义测试的输入格式 第一行也是唯一一行包含字符串s

示例案例0

样本输入

用于定制测试 3175

样本输出说明 将字符串拆分为素数的3种方法是31,7,5,3,17, 5317,5


您可以将解决此问题看作是在字符串中放置断点 例如:3175可以有如下断点: 31|7|5 我们可以使用递归方法: 在遍历字符串时: 当遇到字符串中的每个数字时,您有两个选择: -在该数字后放置一个断点 -或者不要在该数字后放置断点 放置断点取决于是否可以通过检查预填充的小于100的素数列表中的成员身份来轻松检查从素数遍历的数

Python中的递归解决方案:

listOfPrimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

def splitPrime(string):
    def helper(string, n, i):
        # If we are down to last 1 digit
        if i == n-1:
            if int(string[i]) in listOfPrimes:
                return 1
            else:
                return 0
        # If we are down to last 2 digits
        if i == n-2:
            if int(string[i:]) in listOfPrimes:
                return 1
            else:
                return 0
        else:
            # If single digit is prime, then place breakpoint here
            if int(string[i:i+1]) in listOfPrimes:
                return 1 + helper(string1, n, i+1)
            # If two digits make a prime, then place breakpoint here
            if int(string[i:i+2]) in listOfPrimes:
                return 1 + helper(string, n, i+2)
    n = len(string)
    return helper(string1, n, 0)

string1 = "3175"
string2 = "11373"
print(splitPrime(string1)) # 3
print(splitPrime(string2)) # 3
解释 将长度为4的字符串拆分为所有组合可以通过从000到111的二进制计数来确定。如果存在1,则表示应在该点拆分该字符串

对于字符串3175,我们得到:

3 1 7 5
 0 0 0   3175
 0 0 1   317,5
 0 1 0   31,75
 0 1 1   31,7,5
 1 0 0   3,175
 1 0 1   3,17,5
 1 1 0   3,1,75
 1 1 1   3,1,7,5
说明:

设C[i]=将S[:i]拆分为素数的方法数


如果你的问题与莫尔斯电码打包问题非常相似。唯一的区别是,你不需要一个由有效莫尔斯字符串组成的字母表,而需要建立一个由有效素数组成的字母表。看看吧,如果你懂动态规划,这就足够了。另外,在你的问题的标题中,你说你想计算t可以用素数填充一个字符串的方法有很多,但在示例中,您展示了所有这些。第一个问题可以在多项式时间内解决,而不是第二个问题。编辑注释:由于您必须得到素数,所以这个问题在任何情况下都是弱NP难的。您的问题是字符串可以在r中拆分为素数范围2到100。因此11373只能以3种不同的方式拆分[11,37,3],[11,3,73]和[11,3,7,3]然后使用动态规划,这样你就不会以指数级的复杂度结束。@rishi,你能给我一个代码片段开始吗?谢谢。我已经编辑了我的答案,以提供递归解决方案。如果满意,请接受答案。11373的答案应该是6。错误答案。-1在p上实现缓存是有意义的素数查找,因为您将多次检查同一个数。您解释如何仅通过计数拆分字符串的部分非常有见地。它帮助我解决了一个递归问题,我已经有几个月了。问题是我要找到所有可能的子字符串,我总是遇到堆栈溢出由于递归,所以很低。非常感谢❤️谢谢,我想我们对我的问题有多种解释。一个更新:seiventinput_str+1将更有效,也适用于更大的数字。
[317, 5]
[31, 7, 5]
[3, 17, 5]
3 1 7 5
 0 0 0   3175
 0 0 1   317,5
 0 1 0   31,75
 0 1 1   31,7,5
 1 0 0   3,175
 1 0 1   3,17,5
 1 1 0   3,1,75
 1 1 1   3,1,7,5
# sieve of eratosthenes
def sieve(n):
  isprime = [False, False] + [True]*n
  for p in range(2,n):
    if isprime[p]:
      for kp in range(2*p,n,p):
        isprime[kp] = False
  return isprime

isprime = sieve(100)

# Dynamic programming
# C[i] = number of ways to split S[:i] into primes
def dp(s):
  C = [0]*(len(s)+1)
  for i in range(1,len(s)+1):
    C[i] = sum(C[j] for j in range(i) if isprime[int(s[j:i])]) 
    C[i] += isprime[int(s[:i])]
  return C[len(s)]

print(dp('3175'))