Given two strings S and T and a number K, the task is to count the number of ways to convert string S to string T by performing K cyclic shifts.
The cyclic shift is defined as the string S can be split into two non-empty parts X + Y and in one operation we can transform S to Y + X from X + Y.
Note: Since count can be very large print the answer to modulo 109 + 7.
Examples:
Input: S = “ab”, T = “ab”, K = 2
Output: 1
Explanation:
The only way to do this is to convert [ab to ba] in the first move and then [ba to ab] in the second move.
Input: S = “ababab”, T = “ababab”, K = 1
Output: 2
Explanation:
One possible way to convert S to T in one move is [ab | abab] -> [ababab], the second way is [abab | ab] -> [ababab]. So there are total two ways.
Approach: This problem can be solved using Dynamic Programming. Let us call a cyclic shift ‘good’ if at the end we are at string T and the vice versa for ‘bad’. Below are the steps:
- Precompute the number of good(denoted by a) and bad(denoted by b) cyclic shifts.
- Initialize two dp arrays such that dp1[i] denote the number of ways to get to a good shift in i moves and dp2[i] denotes the number of ways to get to a bad shift in i moves.
- For transition, we are only concerned about previous state i.e., (i – 1)th state and the answer to this question is dp1[K].
- So the number of ways to reach a good state in i moves is equal to the number of ways of reaching a good shift in i-1 moves multiplied by (a-1) (as last shift is also good)
- So the number of ways of reaching a bad shift in i-1 moves multiplied by (a)(as next move can be any of the good shifts).
Below is the recurrence relation for the good and bad shifts:
So for good shifts we have:
Similarly, for bad shifts we have:
Below is the implementation of above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
#define mod 10000000007 // Function to count number of ways to // convert string S to string T by // performing K cyclic shifts long long countWays(string s, string t,
int k)
{ // Calculate length of string
int n = s.size();
// 'a' is no of good cyclic shifts
// 'b' is no of bad cyclic shifts
int a = 0, b = 0;
// Iterate in the string
for ( int i = 0; i < n; i++) {
string p = s.substr(i, n - i)
+ s.substr(0, i);
// Precompute the number of good
// and bad cyclic shifts
if (p == t)
a++;
else
b++;
}
// Initialize two dp arrays
// dp1[i] to store the no of ways to
// get to a good shift in i moves
// dp2[i] to store the no of ways to
// get to a bad shift in i moves
vector< long long > dp1(k + 1), dp2(k + 1);
if (s == t) {
dp1[0] = 1;
dp2[0] = 0;
}
else {
dp1[0] = 0;
dp2[0] = 1;
}
// Calculate good and bad shifts
for ( int i = 1; i <= k; i++) {
dp1[i]
= ((dp1[i - 1] * (a - 1)) % mod
+ (dp2[i - 1] * a) % mod)
% mod;
dp2[i]
= ((dp1[i - 1] * (b)) % mod
+ (dp2[i - 1] * (b - 1)) % mod)
% mod;
}
// Return the required number of ways
return dp1[k];
} // Driver Code int main()
{ // Given Strings
string S = "ab" , T = "ab" ;
// Given K shifts required
int K = 2;
// Function Call
cout << countWays(S, T, K);
return 0;
} |
// Java program for above approach class GFG{
static long mod = 10000000007L;
// Function to count number of ways to // convert string S to string T by // performing K cyclic shifts static long countWays(String s, String t,
int k)
{ // Calculate length of string
int n = s.length();
// 'a' is no of good cyclic shifts
// 'b' is no of bad cyclic shifts
int a = 0 , b = 0 ;
// Iterate in the string
for ( int i = 0 ; i < n; i++)
{
String p = s.substring(i, n - i) +
s.substring( 0 , i);
// Precompute the number of good
// and bad cyclic shifts
if (p == t)
a++;
else
b++;
}
// Initialize two dp arrays
// dp1[i] to store the no of ways to
// get to a good shift in i moves
// dp2[i] to store the no of ways to
// get to a bad shift in i moves
long dp1[] = new long [k + 1 ];
long dp2[] = new long [k + 1 ];
if (s == t)
{
dp1[ 0 ] = 1 ;
dp2[ 0 ] = 0 ;
}
else
{
dp1[ 0 ] = 0 ;
dp2[ 0 ] = 1 ;
}
// Calculate good and bad shifts
for ( int i = 1 ; i <= k; i++)
{
dp1[i] = ((dp1[i - 1 ] * (a - 1 )) % mod +
(dp2[i - 1 ] * a) % mod) % mod;
dp2[i] = ((dp1[i - 1 ] * (b)) % mod +
(dp2[i - 1 ] * (b - 1 )) % mod) % mod;
}
// Return the required number of ways
return dp1[k];
} // Driver code public static void main(String[] args)
{ // Given Strings
String S = "ab" , T = "ab" ;
// Given K shifts required
int K = 2 ;
// Function Call
System.out.print(countWays(S, T, K));
} } // This code is contributed by Pratima Pandey |
# Python3 program for the above approach mod = 1000000007
# Function to count number of ways # to convert string S to string T by # performing K cyclic shifts def countWays(s, t, k):
# Calculate length of string
n = len (s)
# a is no. of good cyclic shifts
# b is no. of bad cyclic shifts
a = 0
b = 0
# Iterate in string
for i in range (n):
p = s[i : ] + s[: i]
# Precompute the number of good
# and bad cyclic shifts
if (p = = t):
a + = 1
else :
b + = 1
# Initialize two dp arrays
# dp1[i] to store the no of ways to
# get to a goof shift in i moves
# dp2[i] to store the no of ways to
# get to a bad shift in i moves
dp1 = [ 0 ] * (k + 1 )
dp2 = [ 0 ] * (k + 1 )
if (s = = t):
dp1[ 0 ] = 1
dp2[ 0 ] = 0
else :
dp1[ 0 ] = 0
dp2[ 0 ] = 1
# Calculate good and bad shifts
for i in range ( 1 , k + 1 ):
dp1[i] = ((dp1[i - 1 ] * (a - 1 )) % mod +
(dp2[i - 1 ] * a) % mod) % mod
dp2[i] = ((dp1[i - 1 ] * (b)) % mod +
(dp2[i - 1 ] * (b - 1 )) % mod) % mod
# Return the required number of ways
return (dp1[k])
# Driver Code # Given Strings S = 'ab'
T = 'ab'
# Given K shifts required K = 2
# Function call print (countWays(S, T, K))
# This code is contributed by Arjun Saini |
// C# program for the above approach using System;
class GFG{
static long mod = 10000000007L;
// Function to count number of ways to // convert string S to string T by // performing K cyclic shifts static long countWays( string s, string t,
int k)
{ // Calculate length of string
int n = s.Length;
// 'a' is no of good cyclic shifts
// 'b' is no of bad cyclic shifts
int a = 0, b = 0;
// Iterate in the string
for ( int i = 0; i < n; i++)
{
string p = s.Substring(i, n - i) +
s.Substring(0, i);
// Precompute the number of good
// and bad cyclic shifts
if (p == t)
a++;
else
b++;
}
// Initialize two dp arrays
// dp1[i] to store the no of ways to
// get to a good shift in i moves
// dp2[i] to store the no of ways to
// get to a bad shift in i moves
long []dp1 = new long [k + 1];
long []dp2 = new long [k + 1];
if (s == t)
{
dp1[0] = 1;
dp2[0] = 0;
}
else
{
dp1[0] = 0;
dp2[0] = 1;
}
// Calculate good and bad shifts
for ( int i = 1; i <= k; i++)
{
dp1[i] = ((dp1[i - 1] * (a - 1)) % mod +
(dp2[i - 1] * a) % mod) % mod;
dp2[i] = ((dp1[i - 1] * (b)) % mod +
(dp2[i - 1] * (b - 1)) % mod) % mod;
}
// Return the required number of ways
return dp1[k];
} // Driver code public static void Main( string [] args)
{ // Given Strings
string S = "ab" , T = "ab" ;
// Given K shifts required
int K = 2;
// Function call
Console.Write(countWays(S, T, K));
} } // This code is contributed by rutvik_56 |
<script> // JavaScript program for the above approach let mod = 10000000007; // Function to count number of ways to // convert string S to string T by // performing K cyclic shifts function countWays(s, t, k)
{ // Calculate length of string
let n = s.length;
// 'a' is no of good cyclic shifts
// 'b' is no of bad cyclic shifts
let a = 0, b = 0;
// Iterate in the string
for (let i = 0; i < n; i++)
{
let p = s.substr(i, n - i) +
s.substr(0, i);
// Precompute the number of good
// and bad cyclic shifts
if (p == t)
a++;
else
b++;
}
// Initialize two dp arrays
// dp1[i] to store the no of ways to
// get to a good shift in i moves
// dp2[i] to store the no of ways to
// get to a bad shift in i moves
let dp1 = Array.from({length: k+1}, (_, i) => 0);
let dp2 = Array.from({length: k+1}, (_, i) => 0);
if (s == t)
{
dp1[0] = 1;
dp2[0] = 0;
}
else
{
dp1[0] = 0;
dp2[0] = 1;
}
// Calculate good and bad shifts
for (let i = 1; i <= k; i++)
{
dp1[i] = ((dp1[i - 1] * (a - 1)) % mod +
(dp2[i - 1] * a) % mod) % mod;
dp2[i] = ((dp1[i - 1] * (b)) % mod +
(dp2[i - 1] * (b - 1)) % mod) % mod;
}
// Return the required number of ways
return dp1[k];
} // Driver Code // Given Strings
let S = "ab" , T = "ab" ;
// Given K shifts required
let K = 2;
// Function Call
document.write(countWays(S, T, K));
</script> |
Output
1
Time Complexity: O(N)
Auxiliary Space: O(K)
Efficient approach: Space optimization O(1)
In the previous approach, the current values dp1[i] and dp2[i] only depend upon the previous value i.e. dp1[i-1] and dp2[i-1]. So to optimize the space we can keep track of previous and current values with the help of 2 variables prev and curr which will reduce the space complexity from O(k) to O(1).
Steps to implement the above approach:
- Create 2 variables for both array dp1_prev and dp2_prev to keep track o previous values of dp1 and dp2.
- Initialize base case dp1_prev and dp2_prev.
- Create a variable current for both dp1_curr and dp2_curr to store the current value.
- Iterate over the subproblem using a loop and update both current values.
- After every iteration update dp1_prev and dp2_prev for further iterations.
- At last return dp1_curr.
Below is the code to implement the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
#define mod 10000000007 // Function to count number of ways to // convert string S to string T by // performing K cyclic shifts long long countWays(string s, string t, int k)
{ // Calculate length of string
int n = s.size();
// 'a' is no of good cyclic shifts
// 'b' is no of bad cyclic shifts
int a = 0, b = 0;
// Iterate in the string
for ( int i = 0; i < n; i++) {
string p = s.substr(i, n - i) + s.substr(0, i);
// Precompute the number of good
// and bad cyclic shifts
if (p == t)
a++;
else
b++;
}
// initialize variables for current and previous values
// of DP1 and DP2
int dp1_curr, dp1_prev, dp2_curr, dp2_prev;
// Base Case
if (s == t) {
dp1_prev = 1;
dp2_prev = 0;
}
else {
dp1_prev = 0;
dp2_prev = 1;
}
// Iterate over subproblems and update current values
for ( int i = 1; i <= k; i++) {
dp1_curr = ((dp1_prev * (a - 1)) % mod
+ (dp2_prev * a) % mod)
% mod;
dp2_curr = ((dp1_prev * (b)) % mod
+ (dp2_prev * (b - 1)) % mod)
% mod;
// assigning values for iterating further
dp1_prev = dp1_curr;
dp2_prev = dp2_curr;
}
// return final answer
return dp1_curr;
} // Driver Code int main()
{ // Given Strings
string S = "ab" , T = "ab" ;
// Given K shifts required
int K = 2;
// Function Call
cout << countWays(S, T, K);
return 0;
} |
import java.util.*;
public class Main {
static long mod = 10000000007L;
public static long countWays(String s, String t, int k) {
// Calculate length of string
int n = s.length();
// 'a' is no of good cyclic shifts
// 'b' is no of bad cyclic shifts
int a = 0 , b = 0 ;
// Iterate in the string
for ( int i = 0 ; i < n; i++) {
String p = s.substring(i, n) + s.substring( 0 , i);
// Precompute the number of good
// and bad cyclic shifts
if (p.equals(t))
a++;
else
b++;
}
// initialize variables for current and previous values
// of DP1 and DP2
long dp1_curr = 0 , dp1_prev, dp2_curr = 0 , dp2_prev;
// Base Case
if (s.equals(t)) {
dp1_prev = 1 ;
dp2_prev = 0 ;
} else {
dp1_prev = 0 ;
dp2_prev = 1 ;
}
// Iterate over subproblems and update current values
for ( int i = 1 ; i <= k; i++) {
dp1_curr = ((dp1_prev * (a - 1 )) % mod
+ (dp2_prev * a) % mod)
% mod;
dp2_curr = ((dp1_prev * b) % mod
+ (dp2_prev * (b - 1 )) % mod)
% mod;
// assigning values for iterating further
dp1_prev = dp1_curr;
dp2_prev = dp2_curr;
}
// return final answer
return dp1_curr;
}
public static void main(String[] args) {
// Given Strings
String S = "ab" , T = "ab" ;
// Given K shifts required
int K = 2 ;
// Function Call
System.out.println(countWays(S, T, K));
}
} |
MOD = 10 * * 9 + 7 # Define a constant for modulo arithmetic
def countWays(s, t, k):
n = len (s)
a, b = 0 , 0 # Initialize counts of good and bad cyclic shifts
# Iterate over all cyclic shifts of s and count good and bad ones
for i in range (n):
p = s[i:] + s[:i] # Compute the i-th cyclic shift of s
if p = = t:
a + = 1
else :
b + = 1
# Initialize variables for DP
dp1_prev, dp2_prev = ( 1 , 0 ) if s = = t else ( 0 , 1 )
dp1_curr, dp2_curr = 0 , 0
# Iterate over subproblems and update DP values
for i in range ( 1 , k + 1 ):
dp1_curr = ((dp1_prev * (a - 1 )) % MOD + (dp2_prev * a) % MOD) % MOD
dp2_curr = ((dp1_prev * b) % MOD + (dp2_prev * (b - 1 )) % MOD) % MOD
# Update previous values for next iteration
dp1_prev, dp2_prev = dp1_curr, dp2_curr
return dp1_curr
# Example usage S = 'ab'
T = 'ab'
K = 2
print (countWays(S, T, K))
|
using System;
public class MainClass {
static long mod = 10000000007L;
public static long countWays( string s, string t, int k)
{
// Calculate length of string
int n = s.Length;
// 'a' is no of good cyclic shifts
// 'b' is no of bad cyclic shifts
int a = 0, b = 0;
// Iterate in the string
for ( int i = 0; i < n; i++) {
string p = s.Substring(i, n - i) + s.Substring(0, i);
// Precompute the number of good
// and bad cyclic shifts
if (p.Equals(t))
a++;
else
b++;
}
// initialize variables for current and previous values
// of DP1 and DP2
long dp1_curr = 0, dp1_prev, dp2_curr = 0, dp2_prev;
// Base Case
if (s.Equals(t)) {
dp1_prev = 1;
dp2_prev = 0;
} else {
dp1_prev = 0;
dp2_prev = 1;
}
// Iterate over subproblems and update current values
for ( int i = 1; i <= k; i++) {
dp1_curr = ((dp1_prev * (a - 1)) % mod
+ (dp2_prev * a) % mod)
% mod;
dp2_curr = ((dp1_prev * b) % mod
+ (dp2_prev * (b - 1)) % mod)
% mod;
// assigning values for iterating further
dp1_prev = dp1_curr;
dp2_prev = dp2_curr;
}
// return final answer
return dp1_curr;
}
public static void Main()
{
// Given Strings
string S = "ab" , T = "ab" ;
// Given K shifts required
int K = 2;
// Function Call
Console.WriteLine(countWays(S, T, K));
}
} |
// Define a constant for modulo arithmetic const MOD = 1000000007; function countWays(s, t, k) {
const n = s.length;
// Initialize counts of good and bad cyclic shifts
let a = 0, b = 0;
// Iterate over all cyclic shifts of s and count good and bad ones
for (let i = 0; i < n; i++) {
// Compute the i-th cyclic shift of s
const p = s.slice(i) + s.slice(0, i);
if (p === t) {
a += 1;
} else {
b += 1;
}
}
// Initialize variables for DP
let dp1_prev, dp2_prev;
if (s === t) {
dp1_prev = 1;
dp2_prev = 0;
} else {
dp1_prev = 0;
dp2_prev = 1;
}
let dp1_curr = 0, dp2_curr = 0;
// Iterate over subproblems and update DP values
for (let i = 1; i <= k; i++) {
dp1_curr = ((dp1_prev * (a - 1)) % MOD + (dp2_prev * a) % MOD) % MOD;
dp2_curr = ((dp1_prev * b) % MOD + (dp2_prev * (b - 1)) % MOD) % MOD;
// Update previous values for the next iteration
dp1_prev = dp1_curr;
dp2_prev = dp2_curr;
}
return dp1_curr;
} // Example usage const S = 'ab' ;
const T = 'ab' ;
const K = 2; console.log(countWays(S, T, K)); // This code is contributed by Samim Hossain Mondal. |
Output
1
Time Complexity: O(N)
Auxiliary Space: O(1)