Rearranging one string to another in Java - java

I am trying to find whether a part of given string A can be or can not be rearranged to given string B (Boolean output).
Since the algorithm must be at most O(n), to ease it, I used stringA.retainAll(stringB), so now I know string A and string B consist of the same set of characters and now the whole task smells like regex.
And .. reading about regex, I might be now having two problems(c).
The question is, do I potentially face a risk of getting O(infinity) by using regex or its more efficient to use StreamAPI with the purpose of finding whether each character of string A has enough duplicates to cover each of character of string B? Let alone regex syntax is not easy to read and build.
As of now, I can't use sorting (any sorting is at least n*log(n)) nor hashsets and the likes (as it eliminates duplicates in both strings).
Thank you.

You can use a HashMap<Character,Integer> to count the number of occurrences of each character of the first String. That would take linear time.
Then, for each Character of the second String, find if it's in the HashMap and decrement the counter (if it's still positive). This will also take linear time, and if you manage to decrement the counters for all the characters of the second String, you succeed.

Related

Why is my String array length 3 instead of 2?

I'm trying to understand regex. I wanted to make a String[] using split to show me how many letters are in a given string expression?
import java.util.*;
import java.io.*;
public class Main {
public static String simpleSymbols(String str) {
String result = "";
String[] alpha = str.split("[\\+\\w\\+]");
int alphaLength = alpha.length;
// System.out.print(alphaLength);
String[] charCount = str.split("[a-z]");
int charCountLength = charCount.length;
System.out.println(charCountLength);
}
}
My input string is "+d+=3=+s+". I split the string to count the number of letters in string. The array length should be two but I'm getting three. Also, I'm trying to make a regex to check the pattern +b+, with b being any letter in the alphabet? Is that correct?
So, a few things pop out to me:
First, your regex looks correct. If you're ever worried about how your regex will perform, you can use https://regexr.com/ to check it out. Just put your regex on the top and enter your string in the bottom to see if it is matching correctly
Second, upon close inspection, I see you're using the split function. While it is convenient for quickly splitting strings, you need to be careful as to what you are splitting on. In this case, you're removing all of the strings that you were initially looking at, which would make it impossible to find. If you print it out, you would notice that the following shows (for an input string of +d+=3=+s+):
+
+=3=+
+
Which shows that you accidentally cut out what you were looking to find in the first place. Now, there are several ways of fixing this, depending on what your criteria is.
Now, if what you wanted was just to separate on all +s and it doesn't matter that you find only what is directly bounded by +s, then split works awesome. Just do str.split("+"), and this will return you a list of the following (for +d+=3=+s+):
d
=3=
s
However, you can see that this poses a few problems. First, it doesn't strip out the =3= that we don't want, and second, it does not truly give us values that are surrounded by a +_+ format, where the underscore represents the string/char you're looking for.
Seeing as you're using +w, you intend to find words that are surrounded by +s. However, if you're just looking to find one character, I would suggest using another like [a-z] or [a-zA-Z] to be more specific. However, if you want to find multiple alphabetical characters, your pattern is fine. You can also add a * (0 or more) or a + (1 or more) at the end of the pattern to dictate what exactly you're looking for.
I won't give you the answer outright, but I'll give you a clue as to what to move towards. Try using a pattern and a matcher to find the regex that you listed above and then if you find a match, make sure to store it somewhere :)
Also, for future reference, you should always start a function name with a lower case, at least in Java. Only constants and class names should start in a capital :)
I am trying to use split to count the number of letters in that string. The array length should be two, but I'm getting three.
The regex in the split functions is used as delimiters and will not be shown in results. In your case "str.split([a-z])" means using alphabets as delimiters to separate your input string, which makes three substrings "(+)|d|(+=3=+)|s|(+)".
If you really want to count the number of letters using "split", use 'str.split("[^a-z]")'. But I would recommend using "java.util.regex.Matcher.find()" in order to find out all letters.
Also, I'm trying to make a regex to check the pattern +b+, with b being any letter in the alphabet? Is that correct?
Similarly, check the functions in "java.util.regex.Matcher".

What's the fastest way to only rotate certain elements in an array?

I'm writing a form of word scrambler for strings which takes all letters except for the first and last, and rotates their positions. However, I am supposed to only look at the second to second last letters. How should I only scramble from the second last letter to the second last letter?
e.g. scramble "string" to "srintg"
I can call Collections.rotate() on an array of characters created by splitting the string, but that will scramble the entire word.
List<String> newWordList = Arrays.asList(word.split(" "));
Collections.rotate(newWordList, -1);
String newWord = String.join("", newWordList);
I want to get the output "srintg", but instead I will get "rintgs".
Provided that your word is long enough for it to be sensible (at least four letters), you can make the approach you present work by rotating a sublist of your list:
Collections.rotate(newWordList.subList(1, newWordList.size() - 1), -1);
List.subList() creates a view of a portion of a List list for the exact purpose of avoiding the need for overloading List methods with versions that operate on indexed sub-ranges of the elements. That's "fast" in the sense of fast to write, and it's fairly clear.
If you are looking for "fast" in a performance sense, however, then splitting and joining strings seems ill-advised. Fastest is probably not something we can offer, as performance needs to be tested, but if I were looking for best performance then I would test at least these general approaches:
Work with an array form of your word
Use String.toCharArray() to obtain your word's letters in array form.
Use an indexed for loop to rotate the characters in the array.
Construct a new String from the modified array (using the appropriate constructor).
Use a StringBuilder to assemble the word
Create a StringBuilder with initial capacity equal to the word length.
Iterate over the word's letters using a CharacterIterator, appending them to the builder in the order required. This can be done in a single pass.
Obtain the result string from the builder.

Fastest way to search string?

what's the fastest way to check if specific letter/number appear in string (and how many times)? For example:
I let user write something and got "Test020301423" (ofc I store that data in string variable). Now I want to count how many times "0" appears in string. What's the fastest/best way to do that?
I assume you want to search for different characters in the string to check the availability and occurrences. If so, you can do the following:
Build a Map<Character, Integer> where you will store each character of the string as key and the occurrences as values. To build this map, you need to iterate through every character of the string. So it will take O(n) times to build the map.
Now for every search, you can just check if any specific character is in the map and if it exists then see the value (occurrences). It will take O(1) for every search.

StackOverflow Error while trying to match a large String with regex

I have a String containing natural numbers and between of them any pattern like (,-) or (,).
With a while - condition i make sure that the given Strings contains as less numbers as a given window size, e.g. 5.
The condition looks like that:
while(discretizedTs.substring(lagWindowStart).matches("(-?,?\\d+,){5,}")) {
}
Where lagWindowStart jumps to the index of the next number or (-,) pattern.
For small Strings this regular expression is working fine (as far as tested).
My Problem is, that for large Strings (and i have to deal with very large Strings normaly) this regular expression caused an SOF.
This happens for example if the String contains more than 17k characters.
Is there a limitation of the length of a String which is to match? or a limit in time the matching must be completed?
I did not know how to solve the given problem without regular expressions.
I hope you have any ideas..
Thank you
best
Default JVM stack size is rather small. You can increase it with -Xss option, eg -Xss1024k, should help.

guess words using dictionary

I am guessing the key of a less-simple simple substitution ciphertext. The rule that I evaluate the correctness of the key is number of english words in the putative decryption.
Are there any tools in java that can check the number of english words in a string. For example,
"thefoitedstateswasat"-> 4 words
"thefortedxyzstateswasathat"->5 words.
I loaded words list and using HashSet as a dictionay. As I dont know the inter-word spaces belong in the text, I can't validate words using simple dictionary.
Thanks.
I gave an answer to a similar question here:
If a word is made up of two valid words
It has some Java-esque pseudocode in it that might be adaptable into something that solves this problem.
Sorry I'm new and does not have the rep to comment yet.
But wouldn't the code be very slow as the number of checks and permutations is very big?
I guess you just have to brute force your way through by using (n-1) words nested for loop. And then search the dictionary for each substring.
Surely there's a better way to test the accuracy of your key?
But that's not the point, here's what I'd do:
Using "quackdogsomethinggodknowswhat"
I'd have a recursive method where starting at the beginning of the string, I'd call a recursive method for all the words with which the subject string starts, in this case "qua", and "quack" with the string not containing the word ("dogsomethinggodknowswhat" for quack). Return whatever is greater: 1 + the greatest value returned out of all your method calls OR 0 + the method call for the string starting at index 1 ("uackdogsomethinggodknowswhat").
This would probably work best if you kept your wordlist in a tree of some sort.
If you need some pseudocode, ask!

Categories