Find the number of ways to form a string of length N that can be rearranged to include S as a substring.
Last Updated :
29 Jan, 2024
Given an integer N and string S of size M, the task is to find the number of ways of forming string of length N such that it is possible to rearrange the string to have S as substring. Print the answer modulo 109 + 7.
Note: All characters of string S are distinct.
Examples:
Input: N = 3, S = "abc"
Output: 6
Explanation: There are 6 strings that can be rearranged to have string S as substring: Those strings are "abc", "acb", "bac", "bca", "cab" and "cba".
Input: N = 4, S = "abc"
Output: 588
Explanation: Some possible strings from 588 strings are "bcaz", "zabc", "abcc" and "abbc" whose characters can be rearranged to have "abc" as substring.
Approach: Implement the idea below to solve the problem
Bitmask Dynamic Programming can be used to solve this problem. We can maintain dp[i][j] stores the number of ways to have string S as the substring if we are at index i with submask j. The submask stores which characters we have already taken into our string. If submask j has 0th bit as set then it means that character at index 0 of string S is already present in our string. At any index i, we have 2 choices:
- Choice 1: Choose any character from string S to be placed at index i.
- Choice 2: Choose any character which is not present in string S to be placed at index i.
Explore all the choices to get the final answer.
Steps to solve the problem:
- Define a recursive function, say countOfArr(idx, bitmask) which returns the number of ways to have string S as a substring if we are at index idx and have selected characters represented by bitmask.
- If we have iterated through the whole string, the check if our string has all the characters which are present in S by comparing the submask. If yes, return 1 else return 0.
- If we are at any other index, iterate over all the characters of string S and place every character at index idx.
- Also place all those characters which are not present in string S at index idx.
- Count all the choices to get the final answer.
Code to implement the approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
// to avoid interger overflow
#define int long long
// Function to find ways to form N sized string which has
// string S as substring after rearranging formed string
int countOfArr(int idx, int bitmask, string& S, int N,
int M, vector<vector<int> >& dp)
{
// base case
if (idx == N) {
return bitmask == ((1 << M) - 1);
}
if (dp[idx][bitmask] != -1)
return dp[idx][bitmask];
int ans = 0;
// Choose any one character of string S to be placed at
// index i
for (int i = 0; i < M; i++) {
ans += countOfArr(idx + 1, bitmask | (1LL << i), S,
N, M, dp);
ans %= MOD;
}
// Choose a character which is not present in string S
// to be placed at index i
ans += ((26 - M)
* countOfArr(idx + 1, bitmask, S, N, M, dp))
% MOD;
// returning final answer
return dp[idx][bitmask] = ans;
}
// Driver Code
int32_t main()
{
// Input
int N = 4, M = 3;
string S = "abc";
// DP array initalized with -1
vector<vector<int> > dp(N + 1,
vector<int>((1 << M), -1));
int bitmask = 0;
// Function Call
cout << countOfArr(0, bitmask, S, N, M, dp) << endl;
return 0;
}
Java
import java.util.Arrays;
class GFG
{
static final int MOD = 1000000007;
// Function to find ways to form N sized
// string which has string S as substring
// after rearranging formed string
static int countOfArr(int idx, int bitmask,
String S, int N, int M,
int[][] dp)
{
// base case
if (idx == N) {
return bitmask == ((1 << M) - 1) ? 1 : 0;
}
if (dp[idx][bitmask] != -1)
return dp[idx][bitmask];
int ans = 0;
// Choose any one character of string S
// to be placed at index i
for (int i = 0; i < M; i++) {
ans += countOfArr(idx + 1, bitmask | (1 << i),
S, N, M, dp);
ans %= MOD;
}
// Choose a character which is not present
// in string S to be placed at index i
ans += ((26 - M) * countOfArr(idx + 1, bitmask, S, N, M, dp)) % MOD;
// returning final answer
return dp[idx][bitmask] = ans;
}
// Driver Code
public static void main(String[] args)
{
// Input
int N = 4, M = 3;
String S = "abc";
// DP array initalized with -1
int[][] dp = new int[N + 1][(1 << M)];
for (int[] row : dp) {
Arrays.fill(row, -1);
}
int bitmask = 0;
// Function Call
System.out.println(countOfArr(0, bitmask, S, N, M, dp));
}
}
Python3
MOD = 10**9 + 7
# Function to find ways to form N sized string which has
# string S as substring after rearranging formed string
def countOfArr(idx, bitmask, S, N, M, dp):
# Base case
if idx == N:
return bitmask == ((1 << M) - 1)
if dp[idx][bitmask] != -1:
return dp[idx][bitmask]
ans = 0
# Choose any one character of string S to be placed at
# index i
for i in range(M):
ans += countOfArr(idx + 1, bitmask | (1 << i), S, N, M, dp)
ans %= MOD
# Choose a character which is not present in string S
# to be placed at index i
ans += ((26 - M) * countOfArr(idx + 1, bitmask, S, N, M, dp)) % MOD
# returning final answer
dp[idx][bitmask] = ans
return ans
# Driver Code
if __name__ == "__main__":
# Input
N = 4
M = 3
S = "abc"
# DP array initialized with -1
dp = [[-1 for _ in range(1 << M)] for _ in range(N + 1)]
bitmask = 0
# Function Call
print(countOfArr(0, bitmask, S, N, M, dp))
C#
using System;
using System.Collections.Generic;
class Program
{
const int MOD = 1000000007;
static long CountOfArr(int idx, int bitmask, string S, int N, int M, long[,] dp)
{
// base case
if (idx == N)
{
return bitmask == ((1 << M) - 1) ? 1 : 0;
}
if (dp[idx, bitmask] != -1)
return dp[idx, bitmask];
long ans = 0;
// Choose any one character of string S to be placed at index i
for (int i = 0; i < M; i++)
{
ans += CountOfArr(idx + 1, bitmask | (1 << i), S, N, M, dp);
ans %= MOD;
}
// Choose a character which is not present in string S to be placed at index i
ans += ((26 - M) * CountOfArr(idx + 1, bitmask, S, N, M, dp)) % MOD;
// returning final answer
return dp[idx, bitmask] = ans;
}
static void Main()
{
// Input
int N = 4, M = 3;
string S = "abc";
// DP array initialized with -1
long[,] dp = new long[N + 1, 1 << M];
for (int i = 0; i <= N; i++)
{
for (int j = 0; j < 1 << M; j++)
{
dp[i, j] = -1;
}
}
int bitmask = 0;
// Function Call
Console.WriteLine(CountOfArr(0, bitmask, S, N, M, dp));
}
}
JavaScript
const MOD = 1e9 + 7;
function GFG(idx, bitmask, S, N, M, dp) {
// base case
if (idx === N) {
return bitmask === (1 << M) - 1 ? 1 : 0;
}
if (dp[idx][bitmask] !== -1) {
return dp[idx][bitmask];
}
let ans = 0;
// Choose any one character of the string S to be placed at index i
for (let i = 0; i < M; i++) {
ans += GFG(idx + 1, bitmask | (1 << i), S, N, M, dp);
ans %= MOD;
}
// Choose a character which is not present in string S to be placed at index i
ans += ((26 - M) * GFG(idx + 1, bitmask, S, N, M, dp)) % MOD;
// returning final answer
dp[idx][bitmask] = ans;
return ans;
}
// Driver Code
function main() {
// Input
let N = 4;
let M = 3;
let S = "abc";
let dp = new Array(N + 1).fill(0).map(() => new Array(1 << M).fill(-1));
let bitmask = 0;
// Function Call
console.log(GFG(0, bitmask, S, N, M, dp));
}
main();
Time Complexity: O( N * 2M), where N is the length of string we have to make and M is the length of input string S.
Auxiliary Space: O(N * 2M)
Similar Reads
Number of ways in which the substring in range [L, R] can be formed using characters out of the range Given a string S and a range [L, R]. The task is to find the number of ways in which the sub-string in the range S[L, R] can be constructed using the characters that exist in the string but do not lie in the range S[L, R]. Examples: Input: s = "cabcaab", l = 1, r = 3 Output: 2 The substring is "abc"
8 min read
Number of ways to form a given String from the given set of Strings Given a string str and an array of strings dictionary[], the task is to find the number of ways str can be formed as a concatenation of strings (any number of times) in a dictionary[]. Examples: Input: str = abab, dictionary[] = { a, b, ab }Output: 4Explanation: There are 4 ways to form string str a
15+ min read
Find the count of sub-strings whose characters can be rearranged to form the given word Given a string str, the task is to find the count of all the sub-strings of length four whose characters can be rearranged to form the word "clap".Examples: Input: str = "clapc" Output: 2 "clap" and "lapc" are the required sub-strings Input: str = "abcd" Output: 0 Approach: For every sub-string of l
6 min read
Rearrange the string to maximize the number of palindromic substrings Given a string S consisting of lowercase characters(a-z) only, the task is to print a new string by rearranging the string in such a way that maximizes the number of palindromic substrings. In case of multiple answers, print any one. Note: even if some substrings coincide, count them as many times a
5 min read
Find the starting indices of the substrings in string (S) which is made by concatenating all words from a list(L) You are given a string S, and a list of words L i.e array/vector of strings (Words in list L are all of the same length). Find the starting indices of the substrings in string S, which contains all the words present in list L. The order of words of list L appearing inside string S does not matter i.
10 min read