📌  相关文章
📜  计算构造目标字符串的方法数量

📅  最后修改于: 2021-05-06 18:56:00             🧑  作者: Mango

给定字符串数组A中,每个具有相同的长度和目标字符串的S,找到方法来构建给定阵列中使用的字符从字符串目标字符串的数目,使得在字符串结构形式的严格使用的字符的索引增加顺序。同一字符串也可以使用多个字符。由于答案可能非常大,因此请对(10 ^ 9 + 7)取模

例子:

Input :  A = ["adc", "aec", "erg"], S = "ac"
Output : 4
Target string can be formed in following ways :
1) 1st character of "adc" and the 3rd character of "adc".
2) 1st character of "adc" and the 3rd character of "aec".
3) 1st character of "aec" and the 3rd character of "adc".
4) 1st character of "aec" and the 3rd character of "aec".

Input : A = ["afsdc", "aeeeedc", "ddegerg"], S = "ae"
Output : 12

方法

  • 我们将使用动态编程来解决该问题。
  • 对于数组中的每个字符串,存储在其中发生的字符字符串中在共同的列表(L)的位置。我们的目标是使用其指数形成一个严格递增序列的字符,所以也无所谓他们来自哪个字符串。
  • 遍历目标字符串,并保留先前选择的索引(prev)的信息。对于目标的当前位置,字符串通过在L中进行搜索来检查此字符是否出现在大于prev的任何索引处。这可以使用递归来幼稚地完成,但是我们可以使用dp表来记住它。
Following are the states of dp :
dp[pos][prev], 
where pos represents the position we are at in the target string, 
and prev represents the previously picked index.
C++
// C++ Program to Count the number of ways to
// construct the target string
#include 
 
using namespace std;
 
int mod = 1000000007;
 
int dp[1000][1000];
 
int calculate(int pos, int prev, string s, vector* index)
{
 
    // base case
    if (pos == s.length())
        return 1;
 
    // If current subproblem has been solved, use the value
    if (dp[pos][prev] != -1)
        return dp[pos][prev];
 
    // current character
    int c = s[pos] - 'a';
 
    // search through all the indiced at which the current
    // character occurs. For each index greater than prev,
    // take the index and move
    // to the next position, and add to the answer.
    int answer = 0;
    for (int i = 0; i < index.size(); i++) {
        if (index[i] > prev) {
            answer = (answer % mod + calculate(pos + 1,
                         index[i], s, index) % mod) % mod;
        }
    }
 
    // Store and return the solution for this subproblem
    return dp[pos][prev] = answer;
}
 
int countWays(vector& a, string s)
{
    int n = a.size();
 
    // preprocess the strings by storing for each
    // character of every string, the index of their
    // occurrence we will use a common list for all
    // because of only the index matter
    // in the string from which the character was picked
    vector index[26];
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < a[i].length(); j++) {
 
            // we are storing j+1 because the initial picked index
            // in the recursive step will ne 0.
            // This is just for ease of implementation
            index[a[i][j] - 'a'].push_back(j + 1);
        }
    }
 
    // initialise dp table. -1 represents that
    // the subproblem hasn't been solved
    memset(dp, -1, sizeof(dp));
 
    return calculate(0, 0, s, index);
}
 
// Driver Code
int main()
{
    vector A;
    A.push_back("adc");
    A.push_back("aec");
    A.push_back("erg");
 
    string S = "ac";
 
    cout << countWays(A, S);
 
    return 0;
}


Java
// Java Program to Count the number of ways to
// conthe target String
import java.util.*;
 
class GFG{
  
static int mod = 1000000007;
  
static int [][]dp = new int[1000][1000];
  
static int calculate(int pos, int prev, String s, Vector index)
{
  
    // base case
    if (pos == s.length())
        return 1;
  
    // If current subproblem has been solved, use the value
    if (dp[pos][prev] != -1)
        return dp[pos][prev];
 
  
    // search through all the indiced at which the current
    // character occurs. For each index greater than prev,
    // take the index and move
    // to the next position, and add to the answer.
    int answer = 0;
    for (int i = 0; i < index.size(); i++) {
        if (index.get(i).compareTo(prev) >= 0) {
            answer = (answer % mod + calculate(pos + 1,
                         index.get(i), s, index) % mod) % mod;
        }
    }
  
    // Store and return the solution for this subproblem
    return dp[pos][prev] = answer;
}
  
static int countWays(Vector a, String s)
{
    int n = a.size();
  
    // preprocess the Strings by storing for each
    // character of every String, the index of their
    // occurrence we will use a common list for all
    // because of only the index matter
    // in the String from which the character was picked
    Vector []index = new Vector[26];
    for (int i = 0; i < 26; i++)
        index[i] = new Vector();
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < a.get(i).length(); j++) {
  
            // we are storing j+1 because the initial picked index
            // in the recursive step will ne 0.
            // This is just for ease of implementation
            index[a.get(i).charAt(j) - 'a'].add(j + 1);
        }
    }
  
    // initialise dp table. -1 represents that
    // the subproblem hasn't been solved
    for(int i = 0;i< 1000;i++)
    {
        for (int j = 0; j < 1000; j++) {
            dp[i][j] = -1;
        }
    }
  
    return calculate(0, 0, s, index[0]);
}
  
// Driver Code
public static void main(String[] args)
{
    Vector A = new Vector();
    A.add("adc");
    A.add("aec");
    A.add("erg");
  
    String S = "ac";
  
    System.out.print(countWays(A, S));
}
}
 
// This code is contributed by Princi Singh


Python 3
# Python 3 Program to Count the number of ways to
# construct the target string
 
mod = 1000000007
 
dp = [[-1 for i in range(1000)] for j in range(1000)];
 
def calculate(pos, prev, s,index):
    # base case
    if (pos == len(s)):
        return 1
 
    # If current subproblem has been solved, use the value
    if (dp[pos][prev] != -1):
        return dp[pos][prev]
 
    # current character
    c = ord(s[pos]) - ord('a');
 
    # search through all the indiced at which the current
    # character occurs. For each index greater than prev,
    # take the index and move
    # to the next position, and add to the answer.
    answer = 0
    for i in range(len(index)):
        if (index[i] > prev):
            answer = (answer % mod + calculate(pos + 1,index[i], s, index) % mod) % mod
             
    dp[pos][prev] = 4
 
    # Store and return the solution for this subproblem
    return dp[pos][prev]
 
def countWays(a, s):
    n = len(a)
 
    # preprocess the strings by storing for each
    # character of every string, the index of their
    # occurrence we will use a common list for all
    # because of only the index matter
    # in the string from which the character was picked
    index = [[] for i in range(26)]
 
    for i in range(n):
        for j in range(len(a[i])):
            # we are storing j+1 because the initial picked index
            # in the recursive step will ne 0.
            # This is just for ease of implementation
            index[ord(a[i][j]) - ord('a')].append(j + 1);
 
    # initialise dp table. -1 represents that
    # the subproblem hasn't been solve
 
    return calculate(0, 0, s, index[0])
 
# Driver Code
if __name__ == '__main__':
    A = []
    A.append("adc")
    A.append("aec")
    A.append("erg")
 
    S = "ac"
 
    print(countWays(A, S))
 
# This code is contributed by Surendra_Gangwar


C#
// C# Program to Count the number of ways to
// conthe target String
using System;
using System.Collections.Generic;
 
class GFG{
   
static int mod = 1000000007;
   
static int [,]dp = new int[1000,1000];
   
static int calculate(int pos, int prev, String s, List index)
{
   
    // base case
    if (pos == s.Length)
        return 1;
   
    // If current subproblem has been solved, use the value
    if (dp[pos,prev] != -1)
        return dp[pos,prev];
  
   
    // search through all the indiced at which the current
    // character occurs. For each index greater than prev,
    // take the index and move
    // to the next position, and add to the answer.
    int answer = 0;
    for (int i = 0; i < index.Count; i++) {
        if (index[i].CompareTo(prev) >= 0) {
            answer = (answer % mod + calculate(pos + 1,
                         index[i], s, index) % mod) % mod;
        }
    }
   
    // Store and return the solution for this subproblem
    return dp[pos,prev] = answer;
}
   
static int countWays(List a, String s)
{
    int n = a.Count;
   
    // preprocess the Strings by storing for each
    // character of every String, the index of their
    // occurrence we will use a common list for all
    // because of only the index matter
    // in the String from which the character was picked
    List []index = new List[26];
    for (int i = 0; i < 26; i++)
        index[i] = new List();
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < a[i].Length; j++) {
   
            // we are storing j+1 because the initial picked index
            // in the recursive step will ne 0.
            // This is just for ease of implementation
            index[a[i][j] - 'a'].Add(j + 1);
        }
    }
   
    // initialise dp table. -1 represents that
    // the subproblem hasn't been solved
    for(int i = 0;i< 1000;i++)
    {
        for (int j = 0; j < 1000; j++) {
            dp[i,j] = -1;
        }
    }
   
    return calculate(0, 0, s, index[0]);
}
   
// Driver Code
public static void Main(String[] args)
{
    List A = new List();
    A.Add("adc");
    A.Add("aec");
    A.Add("erg");
   
    String S = "ac";
   
    Console.Write(countWays(A, S));
}
}
 
// This code is contributed by sapnasingh4991


Python3
from collections import defaultdict,Counter
 
# total ways calculator function
def numWays(words,target):
   
    # length of first word
    m = len(words[0])
     
    # length of the target
    n = len(target)
     
    # stroing in default dict
    positions = defaultdict(Counter)
     
     # traversing array
    for i in range(len(words)):
       
        # traversing like 2d row and col
        for j in range(m):
           
            # store the occurences in dict
            positions[j][words[i][j]] += 1
                 
    # define the back function   
    def back(i, start):
       
        # if i is equal to n
        if i==n:
            return 1
         
        # if start is equal to m
        if start==m:
            return 0
           
        # initilaize the ans with 0 
        ans = 0
         
        # recursive call and store
        # the result in ans variable
        ans += back(i, start + 1)
         
        # check the condition
        if positions[start][target[i]]:
           
            # multiply with the each charecter and the recursive call
            ans += positions[start][target[i]] * back(i + 1, start + 1)
        return ans
  
    return back(0,0)
 
# Function Call
words = ["abba","baab"]
target = "bab"
print(numWays(words,target))
 
# This code is contributed by saikumar kudikala


输出:
4



时间复杂度: O(M * N 2 ),其中M是目标字符串的长度,而N是每个数组字符串的长度。

方法:(动态编程+计数器+双向指针)

  1. 这个想法是通过遍历默认字典中所有可能的位置来首先存储所有出现的字符串
  2. 现在定义另一个函数,并通过将两个指针放在第0个索引上从第0个位置开始,然后开始递归
  3. 对于递归,首先,我们应该定义基本情况,以便在某个时候终止递归

基本情况如下:

主要条件:

  • 现在,我们将执行对递归并检查是否可以从给定的字符串形成目标,如果是,我们将简单地增加计数器:
  • 同样,我们将递归调用与给定的字符串相乘,并检查是否可以从字符串生成目标:
  • 最后,我们返回答案
Time complexity:  O(2^n)
space complexity: O(N)

执行:

Python3

from collections import defaultdict,Counter
 
# total ways calculator function
def numWays(words,target):
   
    # length of first word
    m = len(words[0])
     
    # length of the target
    n = len(target)
     
    # stroing in default dict
    positions = defaultdict(Counter)
     
     # traversing array
    for i in range(len(words)):
       
        # traversing like 2d row and col
        for j in range(m):
           
            # store the occurences in dict
            positions[j][words[i][j]] += 1
                 
    # define the back function   
    def back(i, start):
       
        # if i is equal to n
        if i==n:
            return 1
         
        # if start is equal to m
        if start==m:
            return 0
           
        # initilaize the ans with 0 
        ans = 0
         
        # recursive call and store
        # the result in ans variable
        ans += back(i, start + 1)
         
        # check the condition
        if positions[start][target[i]]:
           
            # multiply with the each charecter and the recursive call
            ans += positions[start][target[i]] * back(i + 1, start + 1)
        return ans
  
    return back(0,0)
 
# Function Call
words = ["abba","baab"]
target = "bab"
print(numWays(words,target))
 
# This code is contributed by saikumar kudikala
输出
4