Given two strings of length n,P = p1...pn and Q = q1...qn, we define M(i, j, k) as the number of mismatches between pi...pi+k-1 and qj..qj+k-1. That is in set notation, M(i, j, k) refers to the size of the set { 0<=x<k | pi+x not equal to qj+x| }.
Given an integer K, your task is to find the maximum length L such that there exists pair of indices (i,j) for which we have M(i, j, L) <= K. Of course, we should also have i+L-1 <=n and j+L-1 <=n.
Input
First line of input contains a single integer T (1 <=T <=10). T test cases follow.
Each test case consists of an integer K and two strings P and Q separated by a single space.
Output
For each test case output a single integer L which is the maximum value for which there exists pair of indices (i,j) such that M(i, j, L) <=K.
Constraints
0 <= K <= length of the string P
Both P & Q would have the same length
The size of each of the string would be at the max 1500
All characters in P & Q are lower-case English letters.
Sample Input
3
2 tabriz torino
0 abacba abcaba
3 helloworld yellomarin
Sample Output
4
3
8
Explanation:
First test-case: If we take "briz" from the first string, and "orin" from the second string, then the number of mismatches between these two substrings is equal to 2, and the length of these substrings are 4. That's we have chosen i=3, j=2, L=4, and we have M(3,2,4) = 2.
Second test-case: Since K=0, we should find the longest common substring for the given input strings. We can choose "aba" as the result, and we don't have longer common substring between two strings. So, the answer is 3 for this test-case. That's we have chosen i=1, j=4, and L=3, and we have M(1,4,3)=0.
Third test-case: We can choose "hellowor" from first string and "yellomar" from the second string. So, we have chosen i=1, j=1, and L=8, and we have M(1,1,8)=3. Of course we can also choose i=2, j=2, and L=8 and we still have M(2,2,8)=3.
here is my implementation
import java.io.*;
import java.util.*;
class Solution {
public static int mismatch(String a, String b, int ii, int jj, int xx) {
int i, j = 0;
for (i = 0; i < xx; i++) {
if (a.charAt(ii) != b.charAt(jj)) {
j++;
}
ii++;
jj++;
}
return j;
}
public static boolean find(int x, String a, String b, int kx) {
int nn = a.length();
for (int i = 0; i <= (nn - x); i++) {
for (int j = 0; j <= (nn - x); j++) {
int k;
k = mismatch(a, b, i, j, x);
if (k == kx) {
return true;
}
}
}
return false;
}
public static void main(String args[]) throws IOException {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
while (t > 0) {
int k, n;
String a, b;
k = scanner.nextInt();
a = scanner.next();
b = scanner.next();
n = a.length();
int i = (n + k) / 2;
int st = k, en = n
while (i != k || i != n) {
boolean ch = false, chh = false;
ch = find(i, a, b, k);
if (i != n) {
chh = find(i + 1, a, b, k);
}
if (i == n && ch == true) {
System.out.println(i);
break;
}
if (ch == true && chh == false) {
System.out.println(i);
break;
}
if (ch) {
st = i;
i = (i + en + 1) / 2;
} else {
en = i;
i = (st + i) / 2;
}
}
t--;
}
}
}
the above implementation is taking 5.1 sec for input 0f 1500 string length.But maximum time limit in java is 5sec.if any one can improve this code,please kindly share yor thougths
Your code doesn't take 5.1s on the site. They stop running your code as soon as it exceeds the time limit. Your code might be taking even minutes. So, even if you optimize it with this algorithm you will again get 5.1s in details section. So work on your algo, not optimization!
You could make a boolean array compare[n,n], for which compare[i,j]=(a[i]==b[j]). Later use it instead of making repeating comparisons. You'll have incomparably less comparisons and addressing.
public static int mismatch(String a, String b, int ii, int jj, int xx) {
int i, j = 0;
for (i = 0; i < xx; i++) {
if (! compare[ii,jj]) {
j++;
}
ii++;
jj++;
}
return j;
}
Related
Given a String only made of only 2 letters a,b. Now the task is to split this string into exactly 3 groups such that the number of a's in each group must be same. Then find how many such groups are possible.
Example:
Input:
ababab
Possiblities:
ab ab ab
Output:
1 as we can create only 1 such group, with single a in each group
Example:
Input:
ababbabbaaba
Possiblities:
aba bbabba aba
abab babba aba
ababb abba aba
Output:3
as we can create 3 such possible groups with 2 a's in each group.
Now I came across below code that is solving this task.
public static int findGroups(String input) {
int numberOfAs = 0;
for (int i = 0; i < input.length(); i++) {
if (input.charAt(i) == 'a')
numberOfAs++;
}
int n = input.length();
if (numberOfAs == 0) {
return (n - 1) * (n - 2) / 2;
}
if (numberOfAs % 3 != 0)
return 0;
int numberOfAsInAGroup = numberOfAs / 3;
int lastAIn1stGroup = 0; // last occurrence of A in 1st group
int firstAIn2ndGroup = 0; // 1st occurrence of A in 2nd group
int lastAIn2ndGroup = 0; // last occurrence of A in 2nd group
int firstAIn3rdGroup = 0; // 1st occurrence of A in 3rd group
int aCount = 0;
for (int i = 0; i < n; i++) {
if (input.charAt(i) == 'a') {
aCount++;
if (aCount == numberOfAsInAGroup) {
lastAIn1stGroup = i;
} else if (aCount == numberOfAsInAGroup + 1) {
firstAIn2ndGroup = i;
}
if (aCount == 2 * numberOfAsInAGroup) {
lastAIn2ndGroup = i;
} else if (aCount == 2 * numberOfAsInAGroup + 1) {
firstAIn3rdGroup = i;
break;
}
}
}
int betweenSecondAndFirstGroup = firstAIn2ndGroup - lastAIn1stGroup;
int betweenThirdAndSecondGroup = firstAIn3rdGroup - lastAIn2ndGroup;
return betweenSecondAndFirstGroup * betweenThirdAndSecondGroup;
}
This code is working perfectly finw without any errors. But I am trying to understand for past several days what formulas are being used in this code to solve this task.
Part - 1:
if (numberOfAs == 0) {
return (n - 1) * (n - 2) / 2;
}
After searching in google for several hrs I found the explanation here - number-of-ways-of-distributing-n-identical-objects-among-r-groups:
Part - 2:
int betweenSecondAndFirstGroup = firstAIn2ndGroup - lastAIn1stGroup;
int betweenThirdAndSecondGroup = firstAIn3rdGroup - lastAIn2ndGroup;
return betweenSecondAndFirstGroup * betweenThirdAndSecondGroup;
I am not able to understand this part 2 formula, how this is solving the given problem, is there any explanation as mentioned for part 1.
Also just curious to know, is there any alternate version to solve this task without using formulas like this?
It can be done in linear time.
public class Main {
public static int Nth_A_After(String s, int n, int index){
for(int i = index + 1; i < s.length(); i++) {
if(s.charAt(i) == 'a'){
n--;
if(n == 0) return i;
}
}
return -1;
}
public static void main(String[] args) {
String s = "ababab";
int count = 0;
for(int i = 0; i < s.length(); i++) if(s.charAt(i) == 'a') count++;
if(count % 3 != 0) {
System.out.println("Impossible!");
return;
}
int pos = count / 3;
int firstEnd = Nth_A_After(s, pos, -1);
int secondBegin = Nth_A_After(s, 1, firstEnd);
int secondEnd = Nth_A_After(s, pos - 1, secondBegin);
int thirdBegin = Nth_A_After(s, 1, secondEnd);
int leftDif = secondBegin - firstEnd;
int rightDif = thirdBegin - secondEnd;
if(leftDif > 1) leftDif++;
if(rightDif > 1) rightDif++;
System.out.println(leftDif * rightDif);
}
}
I guess there is a problem in your example ababab, since there is more than just one possibility:
1. a ba bab
2. a bab ab
3. ab a bab
4. ab ab ab
The code you're looking at is finding the boundary As of each group, then is counting the number of spaces the dividing line between the groups could go. This depends on the number of Bs separating the groups of As, since these don't affect the count.
The answer is the number of possible dividing lines on the left, times the number on the right.
AA|B|B|AABAA <-- in this example there are 3 on the left
AABBAA|B|AA <-- and 2 on the right
for a total of 6.
AA|BBAA|BAA
AA|BBAAB|AA
AAB|BAA|BAA
AAB|BAAB|AA
AABB|AA|BAA
AABB|AAB|AA
I am trying to write a logic where I want to generate a list of binary strings of given size n and also the string should have maximum of k bits set to 1.
Example:
If n = 3, k = 1 ==> the number of 1's can be 0 or 1.
Then the output should be 000, 001, 010, 100
Below is the logic I have used with the help of this link as a reference:
Here n is same as arr.length.
static void generateAllBinaryStrings(int n, int arr[], int i, List<String> res, int k) {
if (i == n) {
StringBuilder sb = new StringBuilder();
int count = 0;
for (int j = 0; j < arr.length; j++) {
int val = arr[j];
if (val == 1) {
count++;
}
sb.append(val);
}
if (count <= k) {
res.add(sb.toString());
}
return;
}
arr[i] = 0;
generateAllBinaryStrings(n, arr, i + 1, res, k);
arr[i] = 1;
generateAllBinaryStrings(n, arr, i + 1, res, k);
}
public static void main(String args[]) {
int n = 3;
int[] arr = new int[n];
int k = 1;
int i = 0;
List<String> res = new ArrayList<>();
generateAllBinaryStrings(n, arr, i, res, k);
System.out.println(res);// Prints [000, 001, 010, 100]
}
This code is working fine, but this logic generates all possible binary string then filters based on the number of 1's in the string.
Is there any less time complex algorithm for this problem.
The basic thing that comes into my mind while you are trying to generate the string with having this much data with you why cant you just have one more reference to your recursive call that tell how many 1 are there in you generated string as of the recursion in being called.
The method signature now might look like -
static void generateAllBinaryStrings(int n, int arr[], int i, List<String> res, int k,int currentCountOfOnes){
// Rest logic remains same , each time you don't have to check how many 1's
// are there as of the call made.
}
This might reduce complexity a bit more than what you have.
And one more obvious thing that you can think of is storing your previous called result (memorization -> that leads to a thought of dynamic programming)
Hope thoughts might have helped you.
Note : I could have coded all this but then there is no use of doing so. Try it out if you find it useful do let me know !!
I've come up with this:
static void generateAllBinaryStrings(StringBuilder sb, int n, Set<String> res, int k) {
int len = sb.length();
if (k == 0) {
repeat(sb, '0', n);
res.add(sb.toString());
sb.setLength(len);
} else {
for (int i = 0; i <= n; ++i) {
repeat(sb, '0', i);
if (i < n) {
sb.append('1');
generateAllBinaryStrings(sb, n-i-1, res, k-1);
} else {
res.add(sb.toString());
}
sb.setLength(len);
}
}
}
private static void repeat(StringBuilder sb, char c, int n) {
for (int j = 0; j < n; ++j) {
sb.append('0');
}
}
The idea is that you have k ones to place in a string of length n; so if k == 0, the only possible value is n zeroes. If k > 0, you can add n zeroes, or i zeros, i being anywhere between 0 and n-1, followed by a 1, recurse for the remaining space and k-1.
If we are given an array arr1 consisting of n integers, we can calculate the depth of it in the following way as in image.
The first line of input contains 3 integers n, a, b where n is the size of array.
The second line of input contains array elements. Now if the depth of array = a/b we need to print "yes" else "no".
I have tried to implement the following code:
public static void solve(int n, int a,int b, int[] arr) {
String result = "";
double depth = 0;
for (int i = 0; i < n - 1; i++) {
depth = (double)((double)(depth + arr[i]) + (double)(1 / arr[i + 1]));
}
double d = (double) a / b;
if (depth == d) {
result = "YES";
} else {
result = "NO";
}
System.out.println(result);
}
I had a problem statement which requires passing 3 different numbers to a method and checking which 3 numbers satisfies a certain constraint.
Here is my code, but I wanted to know instead of creating nested loops, is there any more optimized way of checking which set of triplet satisfies a certain constraint. ?
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Solution
{
static List l = new ArrayList();
static int geometricTrick(String s)
{
int count = 0;
for (int i = 0; i < s.length(); i++)
{
for (int j = 0; j < s.length(); j++)
{
for (int k = 0; k < s.length(); k++)
{
if (is1stConstraintTrue(s, i, j, k) && is2ndConstraintTrue(i, j, k))
{
l.add(new Triplet(i, j, k));
}
}
}
}
count = l.size();
return count;
}
static boolean is2ndConstraintTrue(int i, int j, int k)
{
boolean retVal = false;
double LHS = Math.pow((j + 1), 2);
double RHS = (i + 1) * (k + 1);
if (LHS == RHS)
retVal = true;
else
retVal = false;
return retVal;
}
static boolean is1stConstraintTrue(String s, int i, int j, int k)
{
boolean retVal = false;
char[] localChar = s.toCharArray();
if (localChar[i] == 'a' && localChar[j] == 'b' && localChar[k] == 'c')
{
retVal = true;
}
return retVal;
}
static class Triplet
{
public int i, j, k;
public Triplet(int i, int j, int k)
{
this.i= i;
this.j= j;
this.k= k;
}
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int n = in.nextInt();
String s = in.next();
int result = geometricTrick(s);
System.out.println(result);
}
}
Here are some hints:
Computing the square by multiplication will be faster than using pow
String::toCharray() is expensive. It copies all characters into a new array. Each time you call it. Don't call it multiple times.
If the result is the number of triples, you don't need to build a list. You don't even need to create Triple instances. Just count them.
Nested loops are not inefficient, if you need to iterate all combinations.
To provide you a simple and "stupid" solution to not use those inner loops.
Let's use a Factory like an Iterator. This would "hide" the loop by using condition statement.
public class TripletFactory{
final int maxI, maxJ, maxK;
int i, j ,k;
public TripletFactory(int i, int j, int k){
this.maxI = i;
this.maxJ = j;
this.maxK = k;
}
public Triplet next(){
if(++k > maxK){
k = 0;
if(++j > maxJ){
j = 0;
if(++i > maxI){
return null;
}
}
}
return new Triplet(i,j,k);
}
}
That way, you just have to get a new Triple until a null instance in ONE loop
TripletFactory fact = new TripletFactory(2, 3 ,5);
Triplet t = null;
while((t = fact.next()) != null){
System.out.println(t);
}
//no more Triplet
And use it like you want.
Then, you will have to update your constraint method to take a Triplet and use the getters to check the instance.
That could be a method of Triplet to let it validate itself by the way.
Note :
I used the same notation as the Iterator because we could implement Iterator and Iterable to use a notation like :
for(Triplet t : factory){
...
}
The naive approach you presented has cubic time complexity (three nested for-loops). If you have many occurrences of 'a', 'b' and 'c' within your input, it may be worth wile to first determine the indices of all 'a''s, 'b''s and 'c''s and then check your second condition only over this set.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static List<Integer> getAllOccurrences(String input, char of) {
List<Integer> occurrences = new ArrayList<Integer>();
char[] chars = input.toCharArray();
for (int idx = 0; idx < chars.length; ++idx) {
if (of == chars[idx]) {
occurrences.add(idx);
}
}
return (occurrences);
}
static List<Triplet> geometricTrick(String input){
List<Integer> allAs = getAllOccurrences(input, 'a');
List<Integer> allBs = getAllOccurrences(input, 'b');
List<Integer> allCs = getAllOccurrences(input, 'c');
List<Triplet> solutions = new ArrayList<Triplet>();
// reorder the loops, so that the c-loop is the innermost loop (see
// below why this is useful and how it is exploited).
for (int a : allAs) {
for (int c : allCs) {
// calculate lhs as soon as possible, no need to recalculate the
// same value multiple times
final int lhs = ((a + 1) * (c + 1));
for (int b : allBs) {
final int rhs = ((b + 1) * (b + 1));
if (lhs > rhs) {
continue;
}
/* else */ if (lhs == rhs) {
solutions.add(new Triplet(a, b, c));
}
// by construction, the b-values are in ascending or der.
// Thus if the rhs-value is larger or equal to the
// lhs-value, we can skip all other rhs-values. for this
// lhs-value.
// if (lhs <= rhs) {
break;
// }
}
}
}
return (solutions);
}
static class Triplet {
public final int i;
public final int j;
public final int k;
public Triplet(int i, int j, int k) {
this.i = i;
this.j = j;
this.k = k;
}
}
}
Searching all occurrences of one char within a given String takes O(n) (method getAllOccurrences(...)), calling it three times does not change the complexity (3 * n \in O(n)). Iterating through all possible combinations of a, b and c takes #a * #b * #c time, where #a, #b and #c stay for the count of a's, b's and c's in your input. This gives a total time complexity of O(n + #a * #b * #c).
Note that the worst case time complexity, i.e. if 1/3 of your string consists of a's, 1/3 consists of b's and 1/3 consists of c's, is still cubic.
Here's the Problem Statement :
Given n numbers, you can perform the following operation any number of
times : Choose any subset of the
numbers, none of which are 0.
Decrement the numbers in the subset by
1, and increment the numbers not in
the subset by K. Is it possible to
perform operations such that all
numbers except one of them become 0 ?
Input : The first line contains the
number of test cases T. 2*T lines
follow, 2 for each case. The first
line of a test case contains the
numbers n and K. The next line
contains n numbers, a_1...a_n. Output
: Output T lines, one corresponding to
each test case. For a test case,
output "YES" if there is a sequence of
operations as described, and "NO"
otherwise.
Sample Input :
3
2 1
10 10
3 2
1 2 2
3 2
1 2 3
Sample Output :
YES
YES
NO
Constraints :
1 <= T <= 1000
2 <= n <= 100
1 <= K <= 10
0 <= a_i <= 1000
& here's my code :
import java.util.*;
public class ArrayTransform {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int no_of_tests = sc.nextInt();
int size;
int a[] = new int[100];
boolean yes;
int j;
int k;
for (int i = 0; i < no_of_tests; i++) {
size = sc.nextInt();
k = sc.nextInt();
for (j = 0; j < size; j++) {
a[j] = sc.nextInt();
}
yes = is_possible(a, size, k + 1);
if (yes)
System.out.println("YES\n");
else
System.out.println("NO\n");
}
}
static boolean is_possible(int a[], int size, int k_1) {
int count = 0;
int m[] = { -1, -1 };
int mod;
for (int i = 0; i < size; i++) {
mod = a[i] % k_1;
if (m[0] != mod && m[1] != mod) {
if (m[0] == -1)
m[0] = mod;
else if (m[1] == -1)
m[1] = mod;
else
return false;
}
}
return true;
}
}
if (m[0] != mod && m[1] != mod)
Here instead of && there should be ||. Only one of the m's need to match the mod.