给定字符串数组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是每个数组字符串的长度。
方法:(动态编程+计数器+双向指针)
- 这个想法是通过遍历默认字典中所有可能的位置来首先存储所有出现的字符串
- 现在定义另一个函数,并通过将两个指针放在第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 # initilaize the ans with 0
ans += back(i, start + 1) # recursive call and stroe 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 charecter and the recursive call
- 最后,我们返回答案
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