给定字符串数组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
// construct the 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
// construct the 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)
# storing 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 character 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 是每个数组字符串的长度。
方法:(动态编程+计数器+双指针)
- 这个想法是首先通过遍历默认字典中的所有可能位置来存储字符串的所有出现
- 现在定义另一个函数并通过将两个指针放在第 0 个索引上并从第 0 个位置开始并开始递归
- 首先对于递归,我们应该定义基本情况以便在某个时刻终止递归
下面提到了基本情况:
1.if i==n: # if i is equal to n
return 1 #return
2. if start==m: # if start is equal to m
return 0 #
1.In the first base case if the given i == n that means only one character exists we simple return 1
2. if the start == length of the first character of the string we return 0 since we just terminate our recursion
主要条件:
- 现在我们将执行对递归并检查是否可以从给定的字符串形成目标,如果是,我们将简单地增加计数器:
ans = 0 # initialize the ans with 0
ans += back(i, start + 1) # recursive call and store the result in ans variable
- 同样,我们将递归调用与给定的字符串相乘,并检查是否可以从字符串生成目标:
if positions[start][target[i]]: # check the condition
ans += positions[start][target[i]] * back(i + 1, start + 1) # multiply with the each character and the recursive call
- 最后,我们返回答案
Time complexity: O(2^n)
space complexity: O(N)
执行:
蟒蛇3
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)
# storing 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 character 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
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live