📌  相关文章
📜  将给定的字符串拆分为素数:Digit DP

📅  最后修改于: 2021-04-27 18:05:33             🧑  作者: Mango

给定一个表示较大数字的字符串str ,任务是找到可以分割的最小段数,从而可以分割给定的字符串,使每个段都是1到10 6范围内的质数。

例子:

天真的方法:这个想法是考虑每个前缀最多6个数字(因为给定的质数小于10 6 ),并检查它是否是质数。如果前缀是质数,则递归调用该函数以检查剩余的字符串。如果返回非负数,则认为它是可能的安排。如果所有可能的组合都不返回正数,则打印-1。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
#include 
#include 
using namespace std;
  
// Function to check whether a string
// is a prime number or not
bool checkPrime(string number)
{
    int num = stoi(number);
    for (int i = 2; i * i <= num; i++)
        if ((num % i) == 0)
            return false;
    return true;
}
  
// A recursive function to find the minimum
// number of segments the given string can
// be divided such that every segment is a prime
int splitIntoPrimes(string number)
{
    // If the number is null
    if (number.length() == 0)
        return 0;
  
    // checkPrime function is called to check if
    // the number is a prime or not.
    if (number.length() <= 6 and checkPrime(number))
        return 1;
  
    else {
        int numLen = number.length();
  
        // A very large number denoting maximum
        int ans = 1000000;
  
        // Consider a minimum of 6 and length
        // since the primes are less than 10 ^ 6
        for (int i = 1; i <= 6 && i <= numLen; i++) {
            if (checkPrime(number.substr(0, i))) {
  
                // Recursively call the function
                // to check for the remaining string
                int val = splitIntoPrimes(number.substr(i));
                if (val != -1) {
  
                    // Evaluating minimum splits
                    // into Primes for the suffix
                    ans = min(ans, 1 + val);
                }
            }
        }
  
        // Checks if no combination found
        if (ans == 1000000)
            return -1;
        return ans;
    }
}
  
// Driver code
int main()
{
    cout << splitIntoPrimes("13499315") << "\n";
    cout << splitIntoPrimes("43") << "\n";
    return 0;
}


Java
// Java implementation of the above approach
import java.util.*;
  
class GFG{
   
// Function to check whether a String
// is a prime number or not
static boolean checkPrime(String number)
{
    int num = Integer.valueOf(number);
    for (int i = 2; i * i <= num; i++)
        if ((num % i) == 0)
            return false;
    return true;
}
   
// A recursive function to find the minimum
// number of segments the given String can
// be divided such that every segment is a prime
static int splitIntoPrimes(String number)
{
    // If the number is null
    if (number.length() == 0)
        return 0;
   
    // checkPrime function is called to check if
    // the number is a prime or not.
    if (number.length() <= 6 && checkPrime(number))
        return 1;
   
    else {
        int numLen = number.length();
   
        // A very large number denoting maximum
        int ans = 1000000;
   
        // Consider a minimum of 6 and length
        // since the primes are less than 10 ^ 6
        for (int i = 1; i <= 6 && i <= numLen; i++) {
            if (checkPrime(number.substring(0, i))) {
   
                // Recursively call the function
                // to check for the remaining String
                int val = splitIntoPrimes(number.substring(i));
                if (val != -1) {
   
                    // Evaluating minimum splits
                    // into Primes for the suffix
                    ans = Math.min(ans, 1 + val);
                }
            }
        }
   
        // Checks if no combination found
        if (ans == 1000000)
            return -1;
        return ans;
    }
}
   
// Driver code
public static void main(String[] args)
{
    System.out.print(splitIntoPrimes("13499315")+ "\n");
    System.out.print(splitIntoPrimes("43")+ "\n");
}
}
  
// This code is contributed by Rajput-Ji


Python3
# Python3 implementation of the above approach
  
# Function to check whether a string 
# is a prime number or not
def checkPrime(number) :    
      num = int(number)
      for i in range(2, int(num**0.5)) :
            if((num % i) == 0) :
                 return False
      return True
  
# A recursive function to find the minimum
# number of segments the given string can 
# be divided such that every segment is a prime
def splitIntoPrimes(number) :
      # If the number is null
      if( number == '' ) :
           return 0
  
      # checkPrime function is called to check if 
      # the number is a prime or not.
      if( len(number)<= 6 and checkPrime(number) ) :  
           return 1
      else :
           numLen = len(number)
  
           # A very large number denoting maximum
           ans = 1000000
  
           # Consider a minimum of 6 and length 
           # since the primes are less than 10 ^ 6
           for i in range( 1, (min( 6, numLen ) + 1) ) :    
                 if( checkPrime( number[:i] ) ) :
  
                        # Recursively call the function
                        # to check for the remaining string
                        val = splitIntoPrimes( number[i:] )
                        if(val != -1) :
  
                               # Evaluating minimum splits 
                               # into Primes for the suffix 
                               ans = min(ans, 1 + val)   
       
           # Checks if no combination found  
           if( ans == 1000000 ) :   
                 return -1
           return ans
             
# Driver code
print(splitIntoPrimes("13499315"))
print(splitIntoPrimes("43"))


C#
// C# implementation of the above approach
using System;
  
class GFG{
    
// Function to check whether a String
// is a prime number or not
static bool checkPrime(String number)
{
    int num = Int32.Parse(number);
    for (int i = 2; i * i <= num; i++)
        if ((num % i) == 0)
            return false;
    return true;
}
    
// A recursive function to find the minimum
// number of segments the given String can
// be divided such that every segment is a prime
static int splitIntoPrimes(String number)
{
    // If the number is null
    if (number.Length == 0)
        return 0;
    
    // checkPrime function is called to check if
    // the number is a prime or not.
    if (number.Length <= 6 && checkPrime(number))
        return 1;
    
    else {
        int numLen = number.Length;
    
        // A very large number denoting maximum
        int ans = 1000000;
    
        // Consider a minimum of 6 and length
        // since the primes are less than 10 ^ 6
        for (int i = 1; i <= 6 && i <= numLen; i++) {
            if (checkPrime(number.Substring(0, i))) {
    
                // Recursively call the function
                // to check for the remaining String
                int val = splitIntoPrimes(number.Substring(i));
                if (val != -1) {
    
                    // Evaluating minimum splits
                    // into Primes for the suffix
                    ans = Math.Min(ans, 1 + val);
                }
            }
        }
    
        // Checks if no combination found
        if (ans == 1000000)
            return -1;
        return ans;
    }
}
    
// Driver code
public static void Main(String[] args)
{
    Console.Write(splitIntoPrimes("13499315")+ "\n");
    Console.Write(splitIntoPrimes("43")+ "\n");
}
}
  
// This code is contributed by sapnasingh4991


C++
// C++ implementation of the above approach
#include 
using namespace std;
  
// Function to check whether a string
// is a prime number or not
bool checkPrime(string number)
{
    int num = stoi(number);
    for (int i = 2; i * i <= num; i++)
        if ((num % i) == 0)
            return false;
    return true;
}
  
// A function to find the minimum
// number of segments the given string
// can be divided such that every
// segment is a prime
int splitIntoPrimes(string number)
{
    int numLen = number.length();
  
    // Declare a splitdp[] array
    // and initialize to -1
    int splitDP[numLen + 1];
    memset(splitDP, -1, sizeof(splitDP));
  
    // Build the DP table in
    // a bottom-up manner
    for (int i = 1; i <= numLen; i++) {
  
        // Initially Check if the entire prefix is Prime
        if (i <= 6 && checkPrime(number.substr(0, i)))
            splitDP[i] = 1;
  
        // If the Given Prefix can be split into Primes
        // then for the remaining string from i to j
        // Check if Prime. If yes calculate
        // the minimum split till j
        if (splitDP[i] != -1) {
            for (int j = 1; j <= 6 && i + j <= numLen; j++) {
  
                // To check if the substring from i to j
                // is a prime number or not
                if (checkPrime(number.substr(i, j))) {
  
                    // If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1)
                        splitDP[i + j] = 1 + splitDP[i];
                    else
                        splitDP[i + j] = min(splitDP[i + j],
                                             1 + splitDP[i]);
                }
            }
        }
    }
  
    // Return the minimum number of splits
    // for the entire string
    return splitDP[numLen];
}
  
// Driver code
int main()
{
    cout << splitIntoPrimes("13499315") << "\n";
    cout << splitIntoPrimes("43") << "\n";
    return 0;
}


Java
// Java implementation of the above approach
  
import java.util.*;
  
class GFG{
   
// Function to check whether a String
// is a prime number or not
static boolean checkPrime(String number)
{
    if(number.length()==0)
        return true;
    int num = Integer.parseInt(number);
    for (int i = 2; i * i <= num; i++)
        if ((num % i) == 0)
            return false;
    return true;
}
   
// A function to find the minimum
// number of segments the given String
// can be divided such that every
// segment is a prime
static int splitIntoPrimes(String number)
{
    int numLen = number.length();
   
    // Declare a splitdp[] array
    // and initialize to -1
    int []splitDP = new int[numLen + 1];
    Arrays.fill(splitDP, -1);
   
    // Build the DP table in
    // a bottom-up manner
    for (int i = 1; i <= numLen; i++) {
   
        // Initially Check if the entire prefix is Prime
        if (i <= 6 && checkPrime(number.substring(0, i)))
            splitDP[i] = 1;
   
        // If the Given Prefix can be split into Primes
        // then for the remaining String from i to j
        // Check if Prime. If yes calculate
        // the minimum split till j
        if (splitDP[i] != -1) {
            for (int j = 1; j <= 6 && i + j <= numLen; j++) {
   
                // To check if the subString from i to j
                // is a prime number or not
                if (checkPrime(number.substring(i, i+j))) {
   
                    // If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1)
                        splitDP[i + j] = 1 + splitDP[i];
                    else
                        splitDP[i + j] = Math.min(splitDP[i + j],
                                             1 + splitDP[i]);
                }
            }
        }
    }
   
    // Return the minimum number of splits
    // for the entire String
    return splitDP[numLen];
}
   
// Driver code
public static void main(String[] args)
{
    System.out.print(splitIntoPrimes("13499315")+ "\n");
    System.out.print(splitIntoPrimes("43")+ "\n");
}
}
  
// This code contributed by Princi Singh


Python3
# Python 3 implementation of the above approach
from math import sqrt
  
# Function to check whether a string
# is a prime number or not
def checkPrime(number):
    if(len(number) == 0):
        return True
    num = int(number)
    for i in range(2,int(sqrt(num)) + 1, 1):
        if ((num % i) == 0):
            return False
    return True
  
# A function to find the minimum
# number of segments the given string
# can be divided such that every
# segment is a prime
def splitIntoPrimes(number):
    numLen = len(number)
  
    # Declare a splitdp[] array
    # and initialize to -1
    splitDP = [-1 for i in range(numLen + 1)]
  
    # Build the DP table in
    # a bottom-up manner
    for i in range(1, numLen + 1, 1):
  
        # Initially Check if the entire prefix is Prime
        if (i <= 6 and checkPrime(number[0:i])):
            splitDP[i] = 1
  
        # If the Given Prefix can be split into Primes
        # then for the remaining string from i to j
        # Check if Prime. If yes calculate
        # the minimum split till j
        if (splitDP[i] != -1):
            j = 1
            while(j <= 6 and i + j <= numLen):
  
                # To check if the substring from i to j
                # is a prime number or not
                if (checkPrime(number[i:i+j])):
  
                    # If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1):
                        splitDP[i + j] = 1 + splitDP[i]
                    else:
                        splitDP[i + j] = min(splitDP[i + j], 1 + splitDP[i])
                j += 1
  
    # Return the minimum number of splits
    # for the entire string
    return splitDP[numLen]
  
# Driver code
if __name__ == '__main__':
    print(splitIntoPrimes("13499315"))
    print(splitIntoPrimes("43"))
  
# This code is contributed by Surendra_Gangwar


C#
// C# implementation of the above approach
using System;
  
class GFG{
    
// Function to check whether a String
// is a prime number or not
static bool checkPrime(String number)
{
    if(number.Length==0)
        return true;
    int num = Int32.Parse(number);
    for (int i = 2; i * i <= num; i++)
        if ((num % i) == 0)
            return false;
    return true;
}
    
// A function to find the minimum
// number of segments the given String
// can be divided such that every
// segment is a prime
static int splitIntoPrimes(String number)
{
    int numLen = number.Length;
    
    // Declare a splitdp[] array
    // and initialize to -1
    int []splitDP = new int[numLen + 1];
    for (int i = 0; i <= numLen; i++)
        splitDP[i] = -1;
    
    // Build the DP table in
    // a bottom-up manner
    for (int i = 1; i <= numLen; i++) {
    
        // Initially Check if the entire prefix is Prime
        if (i <= 6 && checkPrime(number.Substring(0, i)))
            splitDP[i] = 1;
    
        // If the Given Prefix can be split into Primes
        // then for the remaining String from i to j
        // Check if Prime. If yes calculate
        // the minimum split till j
        if (splitDP[i] != -1) {
            for (int j = 1; j <= 6 && i + j <= numLen; j++) {
    
                // To check if the subString from i to j
                // is a prime number or not
                if (checkPrime(number.Substring(i, j))) {
    
                    // If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1)
                        splitDP[i + j] = 1 + splitDP[i];
                    else
                        splitDP[i + j] = Math.Min(splitDP[i + j],
                                             1 + splitDP[i]);
                }
            }
        }
    }
    
    // Return the minimum number of splits
    // for the entire String
    return splitDP[numLen];
}
    
// Driver code
public static void Main(String[] args)
{
    Console.Write(splitIntoPrimes("13499315")+ "\n");
    Console.Write(splitIntoPrimes("43")+ "\n");
}
}
  
// This code is contributed by Rajput-Ji


C++
// C++ implementation of the above approach
#include 
using namespace std;
  
// Function to precompute all the primes
// upto 1000000 and store it in a set
// using Sieve of Eratosthenes
void getPrimesFromSeive(set& primes)
{
    bool prime[1000001];
    memset(prime, true, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i * i <= 1000000; i++) {
        if (prime[i] == true) {
            for (int j = i * i; j <= 1000000; j += i)
                prime[j] = false;
        }
    }
  
    // Here to_string() is used
    // for converting int to string
    for (int i = 2; i <= 1000000; i++) {
        if (prime[i] == true)
            primes.insert(to_string(i));
    }
}
  
// A function to find the minimum
// number of segments the given string
// can be divided such that every
// segment is a prime
int splitIntoPrimes(string number)
{
    int numLen = number.length();
  
    // Declare a splitdp[] array
    // and initialize to -1
    int splitDP[numLen + 1];
    memset(splitDP, -1, sizeof(splitDP));
  
    // Call sieve function to store primes in
    // primes array
    set primes;
    getPrimesFromSeive(primes);
  
    // Build the DP table in a bottom-up manner
    for (int i = 1; i <= numLen; i++) {
  
        // If the prefix is prime then the prefix
        // will be found in the prime set
        if (i <= 6 && (primes.find(number.substr(0, i))
                       != primes.end()))
            splitDP[i] = 1;
  
        // If the Given Prefix can be split into Primes
        // then for the remaining string from i to j
        // Check if Prime. If yes calculate
        // the minimum split till j
        if (splitDP[i] != -1) {
            for (int j = 1; j <= 6 && i + j <= numLen; j++) {
  
                // To check if the substring from i to j
                // is a prime number or not
                if (primes.find(number.substr(i, j))
                    != primes.end()) {
  
                    // If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1)
                        splitDP[i + j] = 1 + splitDP[i];
                    else
                        splitDP[i + j] = min(splitDP[i + j],
                                             1 + splitDP[i]);
                }
            }
        }
    }
  
    // Return the minimum number of splits
    // for the entire string
    return splitDP[numLen];
}
  
int main()
{
    cout << splitIntoPrimes("13499315") << "\n";
    cout << splitIntoPrimes("43") << "\n";
    return 0;
}


Java
// Java implementation of the above approach
  
import java.util.*;
  
class GFG{
   
// Function to precompute all the primes
// upto 1000000 and store it in a set
// using Sieve of Eratosthenes
static void getPrimesFromSeive(HashSet primes)
{
    boolean []prime = new boolean[1000001];
    Arrays.fill(prime, true);
    prime[0] = prime[1] = false;
    for (int i = 2; i * i <= 1000000; i++) {
        if (prime[i] == true) {
            for (int j = i * i; j <= 1000000; j += i)
                prime[j] = false;
        }
    }
   
    // Here to_String() is used
    // for converting int to String
    for (int i = 2; i <= 1000000; i++) {
        if (prime[i] == true)
            primes.add(String.valueOf(i));
    }
}
   
// A function to find the minimum
// number of segments the given String
// can be divided such that every
// segment is a prime
static int splitIntoPrimes(String number)
{
    int numLen = number.length();
   
    // Declare a splitdp[] array
    // and initialize to -1
    int []splitDP = new int[numLen + 1];
    Arrays.fill(splitDP, -1);
   
    // Call sieve function to store primes in
    // primes array
    HashSet primes = new HashSet();
    getPrimesFromSeive(primes);
   
    // Build the DP table in a bottom-up manner
    for (int i = 1; i <= numLen; i++) {
   
        // If the prefix is prime then the prefix
        // will be found in the prime set
        if (i <= 6 && (primes.contains(number.substring(0, i))))
            splitDP[i] = 1;
   
        // If the Given Prefix can be split into Primes
        // then for the remaining String from i to j
        // Check if Prime. If yes calculate
        // the minimum split till j
        if (splitDP[i] != -1) {
            for (int j = 1; j <= 6 && i + j <= numLen; j++) {
   
                // To check if the subString from i to j
                // is a prime number or not
                if (primes.contains(number.substring(i, i+j))) {
   
                    // If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1)
                        splitDP[i + j] = 1 + splitDP[i];
                    else
                        splitDP[i + j] = Math.min(splitDP[i + j],
                                             1 + splitDP[i]);
                }
            }
        }
    }
   
    // Return the minimum number of splits
    // for the entire String
    return splitDP[numLen];
}
   
public static void main(String[] args)
{
    System.out.print(splitIntoPrimes("13499315")+ "\n");
    System.out.print(splitIntoPrimes("43")+ "\n");
}
}
  
// This code contributed by Princi Singh


Python3
# Python3 implementation of the above approach
  
# Function to precompute all the primes
# upto 1000000 and store it in a set
# using Sieve of Eratosthenes
def getPrimesFromSeive(primes):
  
    prime = [True] * (1000001)
    prime[0], prime[1] = False, False
    i = 2
    while (i * i <= 1000000):
        if (prime[i] == True):
            for j in range(i * i, 1000001, i):
                prime[j] = False
        i += 1
  
    # Here str() is used for
    # converting int to string
    for i in range(2, 1000001):
        if (prime[i] == True):
            primes.append(str(i))
  
# A function to find the minimum
# number of segments the given string
# can be divided such that every
# segment is a prime
def splitIntoPrimes(number):
  
    numLen = len(number)
  
    # Declare a splitdp[] array
    # and initialize to -1
    splitDP = [-1] * (numLen + 1)
  
    # Call sieve function to store 
    # primes in primes array
    primes = []
    getPrimesFromSeive(primes)
  
    # Build the DP table in a bottom-up manner
    for i in range(1, numLen + 1):
  
        # If the prefix is prime then the prefix
        # will be found in the prime set
        if (i <= 6 and (number[0 : i] in primes)):
            splitDP[i] = 1
  
        # If the Given Prefix can be split into Primes
        # then for the remaining string from i to j
        # Check if Prime. If yes calculate
        # the minimum split till j
        if (splitDP[i] != -1):
            j = 1
            while (j <= 6 and (i + j <= numLen)):
  
                # To check if the substring from i to j
                # is a prime number or not
                if (number[i : i + j] in primes):
  
                    # If it is a prime, then 
                    # update the dp array
                    if (splitDP[i + j] == -1):
                        splitDP[i + j] = 1 + splitDP[i]
                    else:
                        splitDP[i + j] = min(splitDP[i + j],
                                         1 + splitDP[i])
                                              
                j += 1
  
    # Return the minimum number of 
    # splits for the entire string
    return splitDP[numLen]
  
# Driver code
print(splitIntoPrimes("13499315"))
print(splitIntoPrimes("43"))
  
# This code is contributed by chitranayal


C#
// C# implementation of the above approach
using System;
using System.Collections.Generic;
  
class GFG{
  
// Function to precompute all the primes
// upto 1000000 and store it in a set
// using Sieve of Eratosthenes
static void getPrimesFromSeive(HashSet primes)
{
    bool []prime = new bool[1000001];
      
    for(int i = 0; i < 1000001; i++)
       prime[i] = true;
    prime[0] = prime[1] = false;
      
    for(int i = 2; i * i <= 1000000; i++)
    {
       if (prime[i] == true)
       {
           for(int j = i * i; j <= 1000000; j += i)
              prime[j] = false;
       }
    }
      
    // Converting int to String
    for(int i = 2; i <= 1000000; i++)
    {
       if (prime[i] == true)
           primes.Add(String.Join("", i));
    }
}
  
// A function to find the minimum
// number of segments the given String
// can be divided such that every
// segment is a prime
static int splitIntoPrimes(String number)
{
    int numLen = number.Length;
  
    // Declare a splitdp[] array
    // and initialize to -1
    int []splitDP = new int[numLen + 1];
    for(int i = 0; i < numLen + 1; i++)
       splitDP[i] = -1;
  
    // Call sieve function to store primes 
    // in primes array
    HashSet primes = new HashSet();
    getPrimesFromSeive(primes);
  
    // Build the DP table in a bottom-up manner
    for(int i = 1; i <= numLen; i++)
    {
         
       // If the prefix is prime then the prefix
       // will be found in the prime set
       if (i <= 6 && (primes.Contains
                     (number.Substring(0, i))))
           splitDP[i] = 1;
         
       // If the given prefix can be split into 
       // primes, then for the remaining String 
       // from i to j check if prime. If yes 
       // calculate the minimum split till j
       if (splitDP[i] != -1)
       {
           for(int j = 1; j <= 6 && i + j <= numLen; j++)
           {
             
              // To check if the subString from 
              // i to j is a prime number or not
              if (primes.Contains(number.Substring(i, j)))
              {
                    
                  // If it is a prime, then update
                  // the dp array
                  if (splitDP[i + j] == -1)
                      splitDP[i + j] = 1 + splitDP[i];
                  else
                      splitDP[i + j] = Math.Min(splitDP[i + j],
                                            1 + splitDP[i]);
              }
           }
       }
    }
  
    // Return the minimum number of 
    // splits for the entire String
    return splitDP[numLen];
}
  
public static void Main(String[] args)
{
    Console.Write(splitIntoPrimes("13499315") + "\n");
    Console.Write(splitIntoPrimes("43") + "\n");
}
}
  
// This code is contributed by sapnasingh4991


输出:
3
1

时间复杂度:

  • 上述方法的时间复杂度为O(N 5/2 ) ,其中N是输入字符串的长度。
  • 递归地找到所有可能组合的复杂度是O(N 2 )
  • 对于每个组合,要检查数字是否为质数,将使用额外的O(N 0.5 )时间。
  • 这使得时间复杂度为O(N 5/2 )

动态编程方法:给定的问题表现出重叠的子问题属性。因此,可以使用动态编程来有效地解决此问题。
定义并使用splitDP []数组,其中splitDP [i]表示长度为’i’的前缀字符串中将其分解为主要细分所需的最小拆分数。

splitDP []数组按以下方式填充:

  1. for循环用于遍历给定字符串的所有索引。
  2. 对于上述循环中的每个索引’i’,从1到6重复另一个循环,以检查第(i + j)索引的子字符串是否形成质数。
  3. 如果它形成质数,则splitDP []上的值将更新为:
    splitDP[i + j] = min(splitDP[i + j], 1 + splitDP[i]);
    
  4. 更新完数组的所有值后,最后一个索引处的值是整个字符串的最小拆分数。

下面是上述方法的实现:

C++

// C++ implementation of the above approach
#include 
using namespace std;
  
// Function to check whether a string
// is a prime number or not
bool checkPrime(string number)
{
    int num = stoi(number);
    for (int i = 2; i * i <= num; i++)
        if ((num % i) == 0)
            return false;
    return true;
}
  
// A function to find the minimum
// number of segments the given string
// can be divided such that every
// segment is a prime
int splitIntoPrimes(string number)
{
    int numLen = number.length();
  
    // Declare a splitdp[] array
    // and initialize to -1
    int splitDP[numLen + 1];
    memset(splitDP, -1, sizeof(splitDP));
  
    // Build the DP table in
    // a bottom-up manner
    for (int i = 1; i <= numLen; i++) {
  
        // Initially Check if the entire prefix is Prime
        if (i <= 6 && checkPrime(number.substr(0, i)))
            splitDP[i] = 1;
  
        // If the Given Prefix can be split into Primes
        // then for the remaining string from i to j
        // Check if Prime. If yes calculate
        // the minimum split till j
        if (splitDP[i] != -1) {
            for (int j = 1; j <= 6 && i + j <= numLen; j++) {
  
                // To check if the substring from i to j
                // is a prime number or not
                if (checkPrime(number.substr(i, j))) {
  
                    // If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1)
                        splitDP[i + j] = 1 + splitDP[i];
                    else
                        splitDP[i + j] = min(splitDP[i + j],
                                             1 + splitDP[i]);
                }
            }
        }
    }
  
    // Return the minimum number of splits
    // for the entire string
    return splitDP[numLen];
}
  
// Driver code
int main()
{
    cout << splitIntoPrimes("13499315") << "\n";
    cout << splitIntoPrimes("43") << "\n";
    return 0;
}

Java

// Java implementation of the above approach
  
import java.util.*;
  
class GFG{
   
// Function to check whether a String
// is a prime number or not
static boolean checkPrime(String number)
{
    if(number.length()==0)
        return true;
    int num = Integer.parseInt(number);
    for (int i = 2; i * i <= num; i++)
        if ((num % i) == 0)
            return false;
    return true;
}
   
// A function to find the minimum
// number of segments the given String
// can be divided such that every
// segment is a prime
static int splitIntoPrimes(String number)
{
    int numLen = number.length();
   
    // Declare a splitdp[] array
    // and initialize to -1
    int []splitDP = new int[numLen + 1];
    Arrays.fill(splitDP, -1);
   
    // Build the DP table in
    // a bottom-up manner
    for (int i = 1; i <= numLen; i++) {
   
        // Initially Check if the entire prefix is Prime
        if (i <= 6 && checkPrime(number.substring(0, i)))
            splitDP[i] = 1;
   
        // If the Given Prefix can be split into Primes
        // then for the remaining String from i to j
        // Check if Prime. If yes calculate
        // the minimum split till j
        if (splitDP[i] != -1) {
            for (int j = 1; j <= 6 && i + j <= numLen; j++) {
   
                // To check if the subString from i to j
                // is a prime number or not
                if (checkPrime(number.substring(i, i+j))) {
   
                    // If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1)
                        splitDP[i + j] = 1 + splitDP[i];
                    else
                        splitDP[i + j] = Math.min(splitDP[i + j],
                                             1 + splitDP[i]);
                }
            }
        }
    }
   
    // Return the minimum number of splits
    // for the entire String
    return splitDP[numLen];
}
   
// Driver code
public static void main(String[] args)
{
    System.out.print(splitIntoPrimes("13499315")+ "\n");
    System.out.print(splitIntoPrimes("43")+ "\n");
}
}
  
// This code contributed by Princi Singh

Python3

# Python 3 implementation of the above approach
from math import sqrt
  
# Function to check whether a string
# is a prime number or not
def checkPrime(number):
    if(len(number) == 0):
        return True
    num = int(number)
    for i in range(2,int(sqrt(num)) + 1, 1):
        if ((num % i) == 0):
            return False
    return True
  
# A function to find the minimum
# number of segments the given string
# can be divided such that every
# segment is a prime
def splitIntoPrimes(number):
    numLen = len(number)
  
    # Declare a splitdp[] array
    # and initialize to -1
    splitDP = [-1 for i in range(numLen + 1)]
  
    # Build the DP table in
    # a bottom-up manner
    for i in range(1, numLen + 1, 1):
  
        # Initially Check if the entire prefix is Prime
        if (i <= 6 and checkPrime(number[0:i])):
            splitDP[i] = 1
  
        # If the Given Prefix can be split into Primes
        # then for the remaining string from i to j
        # Check if Prime. If yes calculate
        # the minimum split till j
        if (splitDP[i] != -1):
            j = 1
            while(j <= 6 and i + j <= numLen):
  
                # To check if the substring from i to j
                # is a prime number or not
                if (checkPrime(number[i:i+j])):
  
                    # If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1):
                        splitDP[i + j] = 1 + splitDP[i]
                    else:
                        splitDP[i + j] = min(splitDP[i + j], 1 + splitDP[i])
                j += 1
  
    # Return the minimum number of splits
    # for the entire string
    return splitDP[numLen]
  
# Driver code
if __name__ == '__main__':
    print(splitIntoPrimes("13499315"))
    print(splitIntoPrimes("43"))
  
# This code is contributed by Surendra_Gangwar

C#

// C# implementation of the above approach
using System;
  
class GFG{
    
// Function to check whether a String
// is a prime number or not
static bool checkPrime(String number)
{
    if(number.Length==0)
        return true;
    int num = Int32.Parse(number);
    for (int i = 2; i * i <= num; i++)
        if ((num % i) == 0)
            return false;
    return true;
}
    
// A function to find the minimum
// number of segments the given String
// can be divided such that every
// segment is a prime
static int splitIntoPrimes(String number)
{
    int numLen = number.Length;
    
    // Declare a splitdp[] array
    // and initialize to -1
    int []splitDP = new int[numLen + 1];
    for (int i = 0; i <= numLen; i++)
        splitDP[i] = -1;
    
    // Build the DP table in
    // a bottom-up manner
    for (int i = 1; i <= numLen; i++) {
    
        // Initially Check if the entire prefix is Prime
        if (i <= 6 && checkPrime(number.Substring(0, i)))
            splitDP[i] = 1;
    
        // If the Given Prefix can be split into Primes
        // then for the remaining String from i to j
        // Check if Prime. If yes calculate
        // the minimum split till j
        if (splitDP[i] != -1) {
            for (int j = 1; j <= 6 && i + j <= numLen; j++) {
    
                // To check if the subString from i to j
                // is a prime number or not
                if (checkPrime(number.Substring(i, j))) {
    
                    // If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1)
                        splitDP[i + j] = 1 + splitDP[i];
                    else
                        splitDP[i + j] = Math.Min(splitDP[i + j],
                                             1 + splitDP[i]);
                }
            }
        }
    }
    
    // Return the minimum number of splits
    // for the entire String
    return splitDP[numLen];
}
    
// Driver code
public static void Main(String[] args)
{
    Console.Write(splitIntoPrimes("13499315")+ "\n");
    Console.Write(splitIntoPrimes("43")+ "\n");
}
}
  
// This code is contributed by Rajput-Ji
输出:
3
1

时间复杂度:

  • 上述方法的时间复杂度为O(N 3/2 ) ,其中N是输入字符串的长度。
  • 遍历所有索引的时间为O(N)
  • 由于内部for循环对每个索引运行固定次数,因此可以将其运行时间视为恒定时间。
  • 对于每个索引,检查数字是否为素数所花费的时间为O(N 0.5 )
  • 因此,总时间复杂度为O(N 3/2 )

优化的动态规划方法:可以通过使用Eratosthenes的Sieve概念预先计算并存储数字是否为质数,并降低每次迭代中检查数字的时间复杂度,从而进一步优化上述方法。

下面是上述方法的实现:

C++

// C++ implementation of the above approach
#include 
using namespace std;
  
// Function to precompute all the primes
// upto 1000000 and store it in a set
// using Sieve of Eratosthenes
void getPrimesFromSeive(set& primes)
{
    bool prime[1000001];
    memset(prime, true, sizeof(prime));
    prime[0] = prime[1] = false;
    for (int i = 2; i * i <= 1000000; i++) {
        if (prime[i] == true) {
            for (int j = i * i; j <= 1000000; j += i)
                prime[j] = false;
        }
    }
  
    // Here to_string() is used
    // for converting int to string
    for (int i = 2; i <= 1000000; i++) {
        if (prime[i] == true)
            primes.insert(to_string(i));
    }
}
  
// A function to find the minimum
// number of segments the given string
// can be divided such that every
// segment is a prime
int splitIntoPrimes(string number)
{
    int numLen = number.length();
  
    // Declare a splitdp[] array
    // and initialize to -1
    int splitDP[numLen + 1];
    memset(splitDP, -1, sizeof(splitDP));
  
    // Call sieve function to store primes in
    // primes array
    set primes;
    getPrimesFromSeive(primes);
  
    // Build the DP table in a bottom-up manner
    for (int i = 1; i <= numLen; i++) {
  
        // If the prefix is prime then the prefix
        // will be found in the prime set
        if (i <= 6 && (primes.find(number.substr(0, i))
                       != primes.end()))
            splitDP[i] = 1;
  
        // If the Given Prefix can be split into Primes
        // then for the remaining string from i to j
        // Check if Prime. If yes calculate
        // the minimum split till j
        if (splitDP[i] != -1) {
            for (int j = 1; j <= 6 && i + j <= numLen; j++) {
  
                // To check if the substring from i to j
                // is a prime number or not
                if (primes.find(number.substr(i, j))
                    != primes.end()) {
  
                    // If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1)
                        splitDP[i + j] = 1 + splitDP[i];
                    else
                        splitDP[i + j] = min(splitDP[i + j],
                                             1 + splitDP[i]);
                }
            }
        }
    }
  
    // Return the minimum number of splits
    // for the entire string
    return splitDP[numLen];
}
  
int main()
{
    cout << splitIntoPrimes("13499315") << "\n";
    cout << splitIntoPrimes("43") << "\n";
    return 0;
}

Java

// Java implementation of the above approach
  
import java.util.*;
  
class GFG{
   
// Function to precompute all the primes
// upto 1000000 and store it in a set
// using Sieve of Eratosthenes
static void getPrimesFromSeive(HashSet primes)
{
    boolean []prime = new boolean[1000001];
    Arrays.fill(prime, true);
    prime[0] = prime[1] = false;
    for (int i = 2; i * i <= 1000000; i++) {
        if (prime[i] == true) {
            for (int j = i * i; j <= 1000000; j += i)
                prime[j] = false;
        }
    }
   
    // Here to_String() is used
    // for converting int to String
    for (int i = 2; i <= 1000000; i++) {
        if (prime[i] == true)
            primes.add(String.valueOf(i));
    }
}
   
// A function to find the minimum
// number of segments the given String
// can be divided such that every
// segment is a prime
static int splitIntoPrimes(String number)
{
    int numLen = number.length();
   
    // Declare a splitdp[] array
    // and initialize to -1
    int []splitDP = new int[numLen + 1];
    Arrays.fill(splitDP, -1);
   
    // Call sieve function to store primes in
    // primes array
    HashSet primes = new HashSet();
    getPrimesFromSeive(primes);
   
    // Build the DP table in a bottom-up manner
    for (int i = 1; i <= numLen; i++) {
   
        // If the prefix is prime then the prefix
        // will be found in the prime set
        if (i <= 6 && (primes.contains(number.substring(0, i))))
            splitDP[i] = 1;
   
        // If the Given Prefix can be split into Primes
        // then for the remaining String from i to j
        // Check if Prime. If yes calculate
        // the minimum split till j
        if (splitDP[i] != -1) {
            for (int j = 1; j <= 6 && i + j <= numLen; j++) {
   
                // To check if the subString from i to j
                // is a prime number or not
                if (primes.contains(number.substring(i, i+j))) {
   
                    // If it is a prime, then update the dp array
                    if (splitDP[i + j] == -1)
                        splitDP[i + j] = 1 + splitDP[i];
                    else
                        splitDP[i + j] = Math.min(splitDP[i + j],
                                             1 + splitDP[i]);
                }
            }
        }
    }
   
    // Return the minimum number of splits
    // for the entire String
    return splitDP[numLen];
}
   
public static void main(String[] args)
{
    System.out.print(splitIntoPrimes("13499315")+ "\n");
    System.out.print(splitIntoPrimes("43")+ "\n");
}
}
  
// This code contributed by Princi Singh

Python3

# Python3 implementation of the above approach
  
# Function to precompute all the primes
# upto 1000000 and store it in a set
# using Sieve of Eratosthenes
def getPrimesFromSeive(primes):
  
    prime = [True] * (1000001)
    prime[0], prime[1] = False, False
    i = 2
    while (i * i <= 1000000):
        if (prime[i] == True):
            for j in range(i * i, 1000001, i):
                prime[j] = False
        i += 1
  
    # Here str() is used for
    # converting int to string
    for i in range(2, 1000001):
        if (prime[i] == True):
            primes.append(str(i))
  
# A function to find the minimum
# number of segments the given string
# can be divided such that every
# segment is a prime
def splitIntoPrimes(number):
  
    numLen = len(number)
  
    # Declare a splitdp[] array
    # and initialize to -1
    splitDP = [-1] * (numLen + 1)
  
    # Call sieve function to store 
    # primes in primes array
    primes = []
    getPrimesFromSeive(primes)
  
    # Build the DP table in a bottom-up manner
    for i in range(1, numLen + 1):
  
        # If the prefix is prime then the prefix
        # will be found in the prime set
        if (i <= 6 and (number[0 : i] in primes)):
            splitDP[i] = 1
  
        # If the Given Prefix can be split into Primes
        # then for the remaining string from i to j
        # Check if Prime. If yes calculate
        # the minimum split till j
        if (splitDP[i] != -1):
            j = 1
            while (j <= 6 and (i + j <= numLen)):
  
                # To check if the substring from i to j
                # is a prime number or not
                if (number[i : i + j] in primes):
  
                    # If it is a prime, then 
                    # update the dp array
                    if (splitDP[i + j] == -1):
                        splitDP[i + j] = 1 + splitDP[i]
                    else:
                        splitDP[i + j] = min(splitDP[i + j],
                                         1 + splitDP[i])
                                              
                j += 1
  
    # Return the minimum number of 
    # splits for the entire string
    return splitDP[numLen]
  
# Driver code
print(splitIntoPrimes("13499315"))
print(splitIntoPrimes("43"))
  
# This code is contributed by chitranayal

C#

// C# implementation of the above approach
using System;
using System.Collections.Generic;
  
class GFG{
  
// Function to precompute all the primes
// upto 1000000 and store it in a set
// using Sieve of Eratosthenes
static void getPrimesFromSeive(HashSet primes)
{
    bool []prime = new bool[1000001];
      
    for(int i = 0; i < 1000001; i++)
       prime[i] = true;
    prime[0] = prime[1] = false;
      
    for(int i = 2; i * i <= 1000000; i++)
    {
       if (prime[i] == true)
       {
           for(int j = i * i; j <= 1000000; j += i)
              prime[j] = false;
       }
    }
      
    // Converting int to String
    for(int i = 2; i <= 1000000; i++)
    {
       if (prime[i] == true)
           primes.Add(String.Join("", i));
    }
}
  
// A function to find the minimum
// number of segments the given String
// can be divided such that every
// segment is a prime
static int splitIntoPrimes(String number)
{
    int numLen = number.Length;
  
    // Declare a splitdp[] array
    // and initialize to -1
    int []splitDP = new int[numLen + 1];
    for(int i = 0; i < numLen + 1; i++)
       splitDP[i] = -1;
  
    // Call sieve function to store primes 
    // in primes array
    HashSet primes = new HashSet();
    getPrimesFromSeive(primes);
  
    // Build the DP table in a bottom-up manner
    for(int i = 1; i <= numLen; i++)
    {
         
       // If the prefix is prime then the prefix
       // will be found in the prime set
       if (i <= 6 && (primes.Contains
                     (number.Substring(0, i))))
           splitDP[i] = 1;
         
       // If the given prefix can be split into 
       // primes, then for the remaining String 
       // from i to j check if prime. If yes 
       // calculate the minimum split till j
       if (splitDP[i] != -1)
       {
           for(int j = 1; j <= 6 && i + j <= numLen; j++)
           {
             
              // To check if the subString from 
              // i to j is a prime number or not
              if (primes.Contains(number.Substring(i, j)))
              {
                    
                  // If it is a prime, then update
                  // the dp array
                  if (splitDP[i + j] == -1)
                      splitDP[i + j] = 1 + splitDP[i];
                  else
                      splitDP[i + j] = Math.Min(splitDP[i + j],
                                            1 + splitDP[i]);
              }
           }
       }
    }
  
    // Return the minimum number of 
    // splits for the entire String
    return splitDP[numLen];
}
  
public static void Main(String[] args)
{
    Console.Write(splitIntoPrimes("13499315") + "\n");
    Console.Write(splitIntoPrimes("43") + "\n");
}
}
  
// This code is contributed by sapnasingh4991
输出:
3
1

时间复杂度:

  • 这是最有效的方法,因为它以O(N)时间复杂度运行,其中N是输入字符串的长度。
  • 由于Eratosthenes的筛网的运行时间为O(N * log(log(N()))) ,素数列表最多为10 6 ,因此可以计算出预计算复杂度。但是,由于对于任何数量的字符串仅执行一次,因此在计算时间复杂度时不计算在内。