Count number of ways to convert string S to T by performing K cyclic shifts
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++
#include <bits/stdc++.h>
using namespace std;
#define mod 10000000007
long long countWays(string s, string t,
int k)
{
int n = s.size();
int a = 0, b = 0;
for ( int i = 0; i < n; i++) {
string p = s.substr(i, n - i)
+ s.substr(0, i);
if (p == t)
a++;
else
b++;
}
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;
}
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 dp1[k];
}
int main()
{
string S = "ab" , T = "ab" ;
int K = 2;
cout << countWays(S, T, K);
return 0;
}
|
Java
class GFG{
static long mod = 10000000007L;
static long countWays(String s, String t,
int k)
{
int n = s.length();
int a = 0 , b = 0 ;
for ( int i = 0 ; i < n; i++)
{
String p = s.substring(i, n - i) +
s.substring( 0 , i);
if (p == t)
a++;
else
b++;
}
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 ;
}
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 dp1[k];
}
public static void main(String[] args)
{
String S = "ab" , T = "ab" ;
int K = 2 ;
System.out.print(countWays(S, T, K));
}
}
|
Python3
mod = 1000000007
def countWays(s, t, k):
n = len (s)
a = 0
b = 0
for i in range (n):
p = s[i : ] + s[: i]
if (p = = t):
a + = 1
else :
b + = 1
dp1 = [ 0 ] * (k + 1 )
dp2 = [ 0 ] * (k + 1 )
if (s = = t):
dp1[ 0 ] = 1
dp2[ 0 ] = 0
else :
dp1[ 0 ] = 0
dp2[ 0 ] = 1
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 (dp1[k])
S = 'ab'
T = 'ab'
K = 2
print (countWays(S, T, K))
|
C#
using System;
class GFG{
static long mod = 10000000007L;
static long countWays( string s, string t,
int k)
{
int n = s.Length;
int a = 0, b = 0;
for ( int i = 0; i < n; i++)
{
string p = s.Substring(i, n - i) +
s.Substring(0, i);
if (p == t)
a++;
else
b++;
}
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;
}
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 dp1[k];
}
public static void Main( string [] args)
{
string S = "ab" , T = "ab" ;
int K = 2;
Console.Write(countWays(S, T, K));
}
}
|
Javascript
<script>
let mod = 10000000007;
function countWays(s, t, k)
{
let n = s.length;
let a = 0, b = 0;
for (let i = 0; i < n; i++)
{
let p = s.substr(i, n - i) +
s.substr(0, i);
if (p == t)
a++;
else
b++;
}
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;
}
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 dp1[k];
}
let S = "ab" , T = "ab" ;
let K = 2;
document.write(countWays(S, T, K));
</script>
|
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++
#include <bits/stdc++.h>
using namespace std;
#define mod 10000000007
long long countWays(string s, string t, int k)
{
int n = s.size();
int a = 0, b = 0;
for ( int i = 0; i < n; i++) {
string p = s.substr(i, n - i) + s.substr(0, i);
if (p == t)
a++;
else
b++;
}
int dp1_curr, dp1_prev, dp2_curr, dp2_prev;
if (s == t) {
dp1_prev = 1;
dp2_prev = 0;
}
else {
dp1_prev = 0;
dp2_prev = 1;
}
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;
dp1_prev = dp1_curr;
dp2_prev = dp2_curr;
}
return dp1_curr;
}
int main()
{
string S = "ab" , T = "ab" ;
int K = 2;
cout << countWays(S, T, K);
return 0;
}
|
Java
import java.util.*;
public class Main {
static long mod = 10000000007L;
public static long countWays(String s, String t, int k) {
int n = s.length();
int a = 0 , b = 0 ;
for ( int i = 0 ; i < n; i++) {
String p = s.substring(i, n) + s.substring( 0 , i);
if (p.equals(t))
a++;
else
b++;
}
long dp1_curr = 0 , dp1_prev, dp2_curr = 0 , dp2_prev;
if (s.equals(t)) {
dp1_prev = 1 ;
dp2_prev = 0 ;
} else {
dp1_prev = 0 ;
dp2_prev = 1 ;
}
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;
dp1_prev = dp1_curr;
dp2_prev = dp2_curr;
}
return dp1_curr;
}
public static void main(String[] args) {
String S = "ab" , T = "ab" ;
int K = 2 ;
System.out.println(countWays(S, T, K));
}
}
|
Python3
MOD = 10 * * 9 + 7
def countWays(s, t, k):
n = len (s)
a, b = 0 , 0
for i in range (n):
p = s[i:] + s[:i]
if p = = t:
a + = 1
else :
b + = 1
dp1_prev, dp2_prev = ( 1 , 0 ) if s = = t else ( 0 , 1 )
dp1_curr, dp2_curr = 0 , 0
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
dp1_prev, dp2_prev = dp1_curr, dp2_curr
return dp1_curr
S = 'ab'
T = 'ab'
K = 2
print (countWays(S, T, K))
|
C#
using System;
public class MainClass {
static long mod = 10000000007L;
public static long countWays( string s, string t, int k)
{
int n = s.Length;
int a = 0, b = 0;
for ( int i = 0; i < n; i++) {
string p = s.Substring(i, n - i) + s.Substring(0, i);
if (p.Equals(t))
a++;
else
b++;
}
long dp1_curr = 0, dp1_prev, dp2_curr = 0, dp2_prev;
if (s.Equals(t)) {
dp1_prev = 1;
dp2_prev = 0;
} else {
dp1_prev = 0;
dp2_prev = 1;
}
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;
dp1_prev = dp1_curr;
dp2_prev = dp2_curr;
}
return dp1_curr;
}
public static void Main()
{
string S = "ab" , T = "ab" ;
int K = 2;
Console.WriteLine(countWays(S, T, K));
}
}
|
Javascript
const MOD = 1000000007;
function countWays(s, t, k) {
const n = s.length;
let a = 0, b = 0;
for (let i = 0; i < n; i++) {
const p = s.slice(i) + s.slice(0, i);
if (p === t) {
a += 1;
} else {
b += 1;
}
}
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;
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;
dp1_prev = dp1_curr;
dp2_prev = dp2_curr;
}
return dp1_curr;
}
const S = 'ab' ;
const T = 'ab' ;
const K = 2;
console.log(countWays(S, T, K));
|
Output
1
Time Complexity: O(N)
Auxiliary Space: O(1)
Last Updated :
02 Nov, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...