📌  相关文章
📜  计算第一个字符串中的子序列,这些子字符串的字谜

📅  最后修改于: 2022-05-13 01:57:08.051000             🧑  作者: Mango

计算第一个字符串中的子序列,这些子字符串的字谜

给定两个长度分别为n1n2的字符串str1str2 。问题是计算str1的所有子序列,它们是str2的字谜。
例子:

Input : str1 = "abacd", str2 = "abc"
Output : 2
Index of characters in the 2 subsequences are:
{0, 1, 3} = {a, b, c} = abc and
{1, 2, 3} = {b, a, c} = bac
The above two subsequences of str1 
are anagrams of str2.

Input : str1 = "geeksforgeeks", str2 = "geeks" 
Output : 48

方法:创建两个数组freq1[]freq2[] ,每个大小为'26',实现为哈希表,分别存储str1str2每个字符的频率。令n1n2分别为str1str2的长度。现在实现以下算法:

countSubsequences(str1, str2)
        for i = 0 to n1-1
        freq1[str1[i] - 'a']++
    for i = 0 n2-1    
        freq2[str2[i] - 'a']++

    Initialize count = 1    
    for i = 0 to 25
        if freq2[i] != 0 then
            if freq2[i] <= freq1[i] then
            count = count * binomialCoeff(freq1[i], freq2[i])
        else
            return 0    
        return count

让 freq1[i] 表示为n , freq2[i] 表示为r 。现在,上面算法中提到的binomialCoeff(n, r)只不过是二项式系数n C r 。参考这篇文章的实现。
解释:
让某个字符的频率在'str2'中说ch是'x',在'str1'中是'y'。如果 y < x,则不存在“str1”的子序列,它可能是“str2”的字谜。否则, y C x给出所选ch的出现次数,这将有助于所需子序列的总数。

C++
// C++ implementation to
// count subsequences in
// first string which are 
// anagrams of the second
// string
#include 
using namespace std;
 
#define SIZE 26
 
// Returns value of Binomial
// Coefficient C(n, k)
int binomialCoeff(int n, int k)
{
    int res = 1;
 
    // Since C(n, k) = C(n, n-k)
    if (k > n - k)
        k = n - k;
 
    // Calculate value of
    // [n * (n-1) *---* (n-k+1)] /
    // [k * (k-1) *----* 1]
    for (int i = 0; i < k; ++i) {
        res *= (n - i);
        res /= (i + 1);
    }
 
    return res;
}
 
// function to count subsequences
// in first string which are
// anagrams of the second string
int countSubsequences(string str1, string str2)
{
    // hash tables to store frequencies
    // of each character
    int freq1[SIZE], freq2[SIZE];
 
    int n1 = str1.size();
    int n2 = str2.size();
 
    // Initialize
    memset(freq1, 0, sizeof(freq1));
    memset(freq2, 0, sizeof(freq2));
 
    // store frequency of each
    // character of 'str1'
    for (int i = 0; i < n1; i++)
        freq1[str1[i] - 'a']++;
 
    // store frequency of each
    // character of 'str2'
    for (int i = 0; i < n2; i++)
        freq2[str2[i] - 'a']++;
 
    // to store the total count
    // of subsequences
    int count = 1;
 
    for (int i = 0; i < SIZE; i++)
 
        // if character (i + 'a')
        // exists in 'str2'
        if (freq2[i] != 0) {
 
                // if this character's frequency
                // in 'str2' in less than or
                // equal to its frequency in
                // 'str1' then accumulate its
                // contribution to the count
                // of subsequences. If its
                // frequency in 'str1' is 'n'
                // and in 'str2' is 'r', then
                // its contribution will be nCr,
                //  where C is the binomial
                // coefficient.
            if (freq2[i] <= freq1[i])
                count = count * binomialCoeff(freq1[i], freq2[i]);
 
            // else return 0 as there could
            // be no subsequence which is an
            // anagram of 'str2'
            else
                return 0;
        }
 
    // required count of subsequences
    return count;
}
 
// Driver program to test above
int main()
{
    string str1 = "abacd";
    string str2 = "abc";
    cout << "Count = "
        << countSubsequences(str1, str2);
    return 0;
}


Java
// Java implementation to
// count subsequences in
// first string which are
// anagrams of the second
// string
import java.util.*;
import java.lang.*;
 
public class GfG{
     
    public final static int SIZE = 26;
     
    // Returns value of Binomial
    // Coefficient C(n, k)
    public static int binomialCoeff(int n,
                                    int k)
    {
        int res = 1;
 
        // Since C(n, k) = C(n, n-k)
        if (k > n - k)
            k = n - k;
 
        // Calculate value of
        // [n * (n-1) *---* (n-k+1)] /
        // [k * (k-1) *----* 1]
        for (int i = 0; i < k; ++i)
        {
            res *= (n - i);
            res /= (i + 1);
        }
 
        return res;
    }
 
    // function to count subsequences
    // in first string which are
    // anagrams of the second string
    public static int countSubsequences(String str,
                                        String str3)
    {
        // hash tables to store frequencies
        // of each character
        int[] freq1 = new int [SIZE];
        int[] freq2 = new int [SIZE];
 
        char[] str1 = str.toCharArray();
        char[] str2 = str3.toCharArray();
         
        int n1 = str.length();
        int n2 = str3.length();
 
        // store frequency of each
        // character of 'str1'
        for (int i = 0; i < n1; i++)
            freq1[str1[i] - 'a']++;
 
        // store frequency of each
        // character of 'str2'
        for (int i = 0; i < n2; i++)
            freq2[str2[i] - 'a']++;
 
        // to store the total count
        // of subsequences
        int count = 1;
 
        for (int i = 0; i < SIZE; i++)
 
            // if character (i + 'a')
            // exists in 'str2'
            if (freq2[i] != 0) {
 
                // if this character's frequency
                // in 'str2' in less than or
                // equal to its frequency in
                // 'str1' then accumulate its
                // contribution to the count
                // of subsequences. If its
                // frequency in 'str1' is 'n'
                // and in 'str2' is 'r', then
                // its contribution will be nCr,
                // where C is the binomial
                // coefficient.
                if (freq2[i] <= freq1[i])
                    count = count * binomialCoeff(freq1[i], freq2[i]);
 
                // else return 0 as there could
                // be no subsequence which is an
                // anagram of 'str2'
                else
                    return 0;
            }
 
        // required count of subsequences
        return count;
    }
     
    // Driver function
    public static void main(String argc[])
    {
        String str1 = "abacd";
        String str2 = "abc";
         
        System.out.println("Count = " +
        countSubsequences(str1, str2));
    }
}
 
/* This code is contributed by Sagar Shukla */


Python
# Python3 implementation to count
# subsequences in first which are
# anagrams of the second
 
# import library
import numpy as np
 
SIZE = 26
 
# Returns value of Binomial
# Coefficient C(n, k)
def binomialCoeff(n, k):
     
    res = 1
 
    # Since C(n, k) = C(n, n-k)
    if (k > n - k):
        k = n - k
 
    # Calculate value of
    # [n * (n-1) *---* (n-k+1)] /
    # [k * (k-1) *----* 1]
    for i in range(0, k):
        res = res * (n - i)
        res = int(res / (i + 1))
     
    return res
 
 
# Function to count subsequences
# in first which are anagrams
# of the second
def countSubsequences(str1, str2):
     
    # Hash tables to store frequencies
    # of each character
    freq1 = np.zeros(26, dtype = np.int)
    freq2 = np.zeros(26, dtype = np.int)
 
    n1 = len(str1)
    n2 = len(str2)
 
    # Store frequency of each
    # character of 'str1'
    for i in range(0, n1):
        freq1[ord(str1[i]) - ord('a') ] += 1
 
    # Store frequency of each
    # character of 'str2'
    for i in range(0, n2):
         
        freq2[ord(str2[i]) - ord('a')] += 1
 
    # To store the total count
    # of subsequences
    count = 1
 
    for i in range(0, SIZE):
         
        # if character (i + 'a')
        # exists in 'str2'
        if (freq2[i] != 0):
            # if this character's frequency
            # in 'str2' in less than or
            # equal to its frequency in
            # 'str1' then accumulate its
            # contribution to the count
            # of subsequences. If its
            # frequency in 'str1' is 'n'
            # and in 'str2' is 'r', then
            # its contribution will be nCr,
            # where C is the binomial
            # coefficient.
            if (freq2[i] <= freq1[i]):
                count = count * binomialCoeff(freq1[i], freq2[i])
 
            # else return 0 as there could
            # be no subsequence which is an
            # anagram of 'str2'
            else:
                return 0
         
    # required count of subsequences
    return count
 
# Driver code
str1 = "abacd"
str2 = "abc"
ans = countSubsequences(str1, str2)
print ("Count = ", ans)
 
 
# This code contributed by saloni1297


C#
// C# implementation to
// count subsequences in
// first string which are
// anagrams of the second
// string
using System;
 
class GfG {
     
    public static int SIZE = 26;
     
    // Returns value of Binomial
    // Coefficient C(n, k)
    public static int binomialCoeff(int n,
                                    int k)
    {
        int res = 1;
 
        // Since C(n, k) = C(n, n-k)
        if (k > n - k)
            k = n - k;
 
        // Calculate value of
        // [n * (n-1) *---* (n-k+1)] /
        // [k * (k-1) *----* 1]
        for (int i = 0; i < k; ++i)
        {
            res *= (n - i);
            res /= (i + 1);
        }
 
        return res;
    }
 
    // function to count subsequences
    // in first string which are
    // anagrams of the second string
    public static int countSubsequences(String str,
                                        String str3)
    {
        // hash tables to store frequencies
        // of each character
        int[] freq1 = new int [SIZE];
        int[] freq2 = new int [SIZE];
 
        char[] str1 = str.ToCharArray();
        char[] str2 = str3.ToCharArray();
         
        int n1 = str.Length;
        int n2 = str3.Length;
 
        // store frequency of each
        // character of 'str1'
        for (int i = 0; i < n1; i++)
            freq1[str1[i] - 'a']++;
 
        // store frequency of each
        // character of 'str2'
        for (int i = 0; i < n2; i++)
            freq2[str2[i] - 'a']++;
 
        // to store the total count
        // of subsequences
        int count = 1;
 
        for (int i = 0; i < SIZE; i++)
 
            // if character (i + 'a')
            // exists in 'str2'
            if (freq2[i] != 0) {
 
                // if this character's frequency
                // in 'str2' in less than or
                // equal to its frequency in
                // 'str1' then accumulate its
                // contribution to the count
                // of subsequences. If its
                // frequency in 'str1' is 'n'
                // and in 'str2' is 'r', then
                // its contribution will be nCr,
                // where C is the binomial
                // coefficient.
                if (freq2[i] <= freq1[i])
                    count = count * binomialCoeff(freq1[i],
                                                  freq2[i]);
 
                // else return 0 as there could
                // be no subsequence which is an
                // anagram of 'str2'
                else
                    return 0;
            }
 
        // required count of subsequences
        return count;
    }
     
    // Driver code
    public static void Main(String[] argc)
    {
        String str1 = "abacd";
        String str2 = "abc";
         
        Console.Write("Count = " +
        countSubsequences(str1, str2));
    }
}
 
// This code is contributed by parashar


PHP
 $n - $k)
        $k = $n - $k;
 
    // Calculate value of
    // [n * (n-1) *---* (n-k+1)] /
    // [k * (k-1) *----* 1]
    for ($i = 0; $i < $k; ++$i)
    {
        $res *= ($n - $i);
        $res /= ($i + 1);
    }
 
    return $res;
}
 
// function to count
// subsequences in
// first string which
// are anagrams of the
// second string
function countSubsequences($str1,
                           $str2)
{
    global $SIZE;
     
    // hash tables to
    // store frequencies
    // of each character
    $freq1 = array();
    $freq2 = array();
 
    // Initialize
    for ($i = 0;
         $i < $SIZE; $i++)
    {
        $freq1[$i] = 0;
        $freq2[$i] = 0;
    }
    $n1 = strlen($str1);
    $n2 = strlen($str2);
 
    // store frequency of each
    // character of 'str1'
    for ($i = 0; $i < $n1; $i++)
        $freq1[ord($str1[$i]) -
               ord('a')]++;
 
    // store frequency of each
    // character of 'str2'
    for ($i = 0; $i < $n2; $i++)
        $freq2[ord($str2[$i]) -
               ord('a')]++;
 
    // to store the total count
    // of subsequences
    $count = 1;
 
    for ($i = 0; $i < $SIZE; $i++)
 
        // if character (i + 'a')
        // exists in 'str2'
        if ($freq2[$i] != 0)
        {
 
            // if this character's frequency
            // in 'str2' in less than or
            // equal to its frequency in
            // 'str1' then accumulate its
            // contribution to the count
            // of subsequences. If its
            // frequency in 'str1' is 'n'
            // and in 'str2' is 'r', then
            // its contribution will be nCr,
            // where C is the binomial
            // coefficient.
            if ($freq2[$i] <= $freq1[$i])
                $count = $count *
                         binomialCoeff($freq1[$i],
                                       $freq2[$i]);
 
            // else return 0 as there
            // could be no subsequence
            // which is an anagram of
            // 'str2'
            else
                return 0;
        }
 
    // required count
    // of subsequences
    return $count;
}
 
// Driver Code
$str1 = "abacd";
$str2 = "abc";
echo ("Count = ".
       countSubsequences($str1,
                         $str2));
 
// This code is contributed by
// Manish Shaw(manishshaw1)
?>


Javascript


输出:

Count = 2

时间复杂度: O(n1 + n2) + O(max),其中max是最大频率。