Concatenate two strings without intersection - java

I need to concatenate two string in another one without their intersection (in terms of last/first words).
In example:
"Some little d" + "little dogs are so pretty" = "Some little dogs are so pretty"
"I love you" + "love" = "I love youlove"
What is the most efficient way to do this in Java?

Here we go - if the first doesn't even contain the first letter of the second string, just return the concatenation. Otherwise, go from longest to shortest on the second string, seeing if the first ends with it. If so, return the non-overlapping parts, otherwise try one letter shorter.
public static String docat(String f, String s) {
if (!f.contains(s.substring(0,1)))
return f + s;
int idx = s.length();
try {
while (!f.endsWith(s.substring(0, idx--))) ;
} catch (Exception e) { }
return f + s.substring(idx + 1);
}
docat("Some little d", "little dogs are so pretty");
-> "Some little dogs are so pretty"
docat("Hello World", "World")
-> "Hello World"
docat("Hello", "World")
-> "HelloWorld"
EDIT: In response to the comment, here is a method using arrays. I don't know how to stress test these properly, but none of them took over 1ms in my testing.
public static String docat2(String first, String second) {
char[] f = first.toCharArray();
char[] s = second.toCharArray();
if (!first.contains("" + s[0]))
return first + second;
int idx = 0;
try {
while (!matches(f, s, idx)) idx++;
} catch (Exception e) { }
return first.substring(0, idx) + second;
}
private static boolean matches(char[] f, char[] s, int idx) {
for (int i = idx; i <= f.length; i++) {
if (f[i] != s[i - idx])
return false;
}
return true;
}

Easiest: iterate over the first string taking suffixes ("Some little d", "ome little d", "me little d"...) and test the second string with .startsWith. When you find a match, concatenate the prefix of the first string with the second string.
Here's the code:
String overlappingConcat(String a, String b) {
int i;
int l = a.length();
for (i = 0; i < l; i++) {
if (b.startsWith(a.substring(i))) {
return a.substring(0, i) + b;
}
}
return a + b;
}
The biggest efficiency problem here is the creation of new strings at substring. Implementing a custom stringMatchFrom(a, b, aOffset) should improve it, and is trivial.

You can avoid creating unnecessary substrings with the regionMatches() method.
public static String intersecting_concatenate(String a, String b) {
// Concatenate two strings, but if there is overlap at the intersection,
// include the intersection/overlap only once.
// find length of maximum possible match
int len_a = a.length();
int len_b = b.length();
int max_match = (len_a > len_b) ? len_b : len_a;
// search down from maximum match size, to get longest possible intersection
for (int size=max_match; size>0; size--) {
if (a.regionMatches(len_a - size, b, 0, size)) {
return a + b.substring(size, len_b);
}
}
// Didn't find any intersection. Fall back to straight concatenation.
return a + b;
}

isBlank(CharSequence), join(T...) and left(String, int) are methods from Apache Commons.
public static String joinOverlap(String s1, String s2) {
if(isBlank(s1) || isBlank(s2)) { //empty or null input -> normal join
return join(s1, s2);
}
int start = Math.max(0, s1.length() - s2.length());
for(int i = start; i < s1.length(); i++) { //this loop is for start point
for(int j = i; s1.charAt(j) == s2.charAt(j-i); j++) { //iterate until mismatch
if(j == s1.length() - 1) { //was it s1's last char?
return join(left(s1, i), s2);
}
}
}
return join(s1, s2); //no overlapping; do normal join
}

Create a suffix tree of the first String, then traverse the tree from the root taking characters from the beginning of the second String and keeping track of the longest suffix found.
This should be the longest suffix of the first String that is a prefix of the second String. Remove the suffix, then append the second String.
This should all be possible in linear time instead of the quadratic time required to loop through and compare all suffixes.

The following code seems to work for the first example. I did not test it extensively, but you get the point. It basically searches for all occurrences of the first char of the secondString in the firstString since these are the only possible places where overlap can occur. Then it checks whether the rest of the first string is the start of the second string. Probably the code contains some errors when no overlap is found, ... but it was more an illustration of my answer
String firstString = "Some little d";
String secondString = "little dogs are so pretty";
String startChar = secondString.substring( 0, 1 );
int index = Math.max( 0, firstString.length() - secondString.length() );
int length = firstString.length();
int searchedIndex = -1;
while ( searchedIndex == -1 && ( index = firstString.indexOf( startChar, index ) )!= -1 ){
if ( secondString.startsWith( firstString.substring( index, length ) ) ){
searchedIndex = index;
}
}
String result = firstString.substring( 0, searchedIndex ) + secondString;

Related

LeetCode 14. longest common prefix

Question:
Write a function to find the longest common prefix string among an array of strings. If there is no common prefix, return an empty string "".
Example 1:
Input: ["flower","flow","flight"]
Output: "fl"
Example 2:
Input: ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.
Code:
public class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs==null || strs.length==0)
return "";
for(int i=0;i<strs[0].length();i++) {
char x = strs[0].charAt(i);
for(int j=0;j<strs.length;j++) {
if((strs[j].length()==i)||(strs[j].charAt(i)!=x)) {
return strs[0].substring(0,i);
}
}
}
return strs[0];
}
}
This is the second solution, but I don't understand the inner loop.
I think if the second element in strs returns a string and ends the for loop, the third element will not have a chance to be compared.
You have to check same position in all of the words and just compare it.
positions
word 0 1 2 3 4 5
=====================
w[0] F L O W E R
w[1] F L O W
w[2] F L I G H T
In Java:
class Main {
public static void main(String[] args) {
String[] words = {"dog","racecar","car"};
String prefix = commonPrefix(words);
System.out.println(prefix);
// return empty string
String[] words2 = {"dog","racecar","car"};
String prefix2 = commonPrefix(words2);
System.out.println(prefix2);
// Return "fl" (2 letters)
}
private static String commonPrefix(String[] words) {
// Common letter counter
int counter = 0;
external:
for (int i = 0; i < words[0].length(); i++) {
// Get letter from first word
char letter = words[0].charAt(i);
// Check rest of the words on that same positions
for (int j = 1; j < words.length; j++) {
// Break when word is shorter or letter is different
if (words[j].length() <= i || letter != words[j].charAt(i)) {
break external;
}
}
// Increase counter, because all of words
// has the same letter (e.g. "E") on the same position (e.g. position "5")
counter++;
}
// Return proper substring
return words[0].substring(0, counter);
}
}
Your first loop is itterating over all chars in the first string of array. Second loop is checking char at i posistion of all strings of array. If characters do not match, or length of string is the same as i it returns substring result.
I think the best way to understand is debug this example.
If the char in the second string is different than the char in the first one, then it is correct to return, since it means that the common prefix ends there. Checking the third and following strings is not necessary.
Basically it returns as soon as it finds a mismatch char.
If we first sort them then it would be very easy we have to only go and compare the first and the last element in the vector present there so,
the code would be like,This is C++ code for the implementation.
class Solution {
public:
string longestCommonPrefix(vector<string>& str) {
int n = str.size();
if(n==0) return "";
string ans = "";
sort(begin(str), end(str));
string a = str[0];
string b = str[n-1];
for(int i=0; i<a.size(); i++){
if(a[i]==b[i]){
ans = ans + a[i];
}
else{
break;
}
}
return ans;
}
};
public class Solution {
public string LongestCommonPrefix(string[] strs) {
if(strs.Length == 0)
{
return string.Empty;
}
var prefix = strs[0];
for(int i=1; i<strs.Length; i++) //always start from 1.index
{
while(!strs[i].StartsWith(prefix))
{
prefix = prefix.Substring(0, prefix.Length-1);
}
}
return prefix;
}
}

Repeatedly removing a substring from a string

Problem: Remove the substring t from a string s, repeatedly and print the number of steps involved to do the same.
Example: t = ab, s = aabb. In the first step, we check if t is contained within s. Here, t is contained in the middle i.e. a(ab)b. So, we will remove it and the resultant will be ab and increment the count value by 1. We again check if t is contained within s. Now, t is equal to s i.e. (ab). So, we remove that from s and increment the count. So, since t is no more contained in s, we stop and print the count value, which is 2 in this case.
I tried to solve this using recursion
static int maxMoves(String s, String t) {
if ( null == s || "" == s || null == t || "" == t){
return 0;
}
int i = s.indexOf(t);
if(i != -1) {
return maxMoves(s.substring(0, i)+ s.substring(i+t.length(), s.length()), t) + 1;
} else {
return 0;
}
}
But I am only passing 9/14 test cases. I also tried this,
static int maxMoves(String s, String t) {
int count = 0,i;
while(true)
{
if(s.contains(t))
{
i = s.indexOf(t);
s = s.substring(0,i) + s.substring(i + t.length());
}
else break;
++count;
}
return count;
}
But that also only passed 9/14 cases.
Could anyone help me figure out which cases I am not covering?
Simply you can use String::replaceFirst with a while loop for example:
String s = "aabb";
String t = "ab";
int count = 0;
while (s.contains(t)) {
s = s.replaceFirst(Pattern.quote(t), "");
count++;
}
System.out.println(count);
Use String#replace
String s = "aabb";
String oldstr = s;
String x = "ab";
while(s.contains(x)){
s = s.replace(x, "");
}
System.out.println((oldstr.length()-s.length())/x.length());
An easy and efficient way is to accumulate the string character-by-character in a StringBuilder; if at any time its buffer ends with the string you want to replace, remove it:
StringBuilder sb = new StringBuilder();
int c = 0;
for (int i = 0; i < s.length(); ++i) {
sb.append(s.charAt(i));
int last = sb.length()-t.length();
if (last >= 0 && sb.indexOf(t, last) == last) {
sb.setLength(last);
++c;
}
}
// c is now the number of times you removed t from s.

How to tackle the Codingbat String-2 oneTwo challenge?

Here is the problem statement:
Given a string, compute a new string by moving the first char to come after the next two chars, so "abc" yields "bca". Repeat this process for each subsequent group of 3 chars, so "abcdef" yields "bcaefd". Ignore any group of fewer than 3 chars at the end.
Here is my code:
// oneTwo("abc") → "bca"
// oneTwo("tca") → "cat"
// oneTwo("tcagdo") → "catdog"
public String oneTwo(String str) {
String x = "";
if (str.length() < 3) {
return "";
// return empty
} else if (str.length() == 3) {
String s = str.substring(1, str.length());
x = s + str.substring(0, 1); // last two + first char
} else if (str.length() > 3) {
int third = 2;
// start with the third element index of 2
for (int i = 0; i < str.length(); i++) {
if (i == third) {
// given three chars substring first char
// substring last two chars and add that to x
x += (str.substring(third - 1, third + 1) +
str.substring(third - 2, third - 2 + 1));
third += 3;
//work with this line but why??????
}
//third +=3;
// doesn't work with this line but why???????
}// end of for loop
}
return x;
// return modified string x
}
With third +=3 inside of if statement work but when I put that outside of if statement I don't get the desired output. I don't really understand why?
Hope this helps:
public String oneTwo(String str) {
String str2 = "";
for(int i=0; i<str.length()-2; i+=3) {
str2 = str2+str.substring(i+1,i+3)+str.charAt(i);
}
return str2;
}
Because putting it outside the loop will cause third to be increased far too often. After the first iteration i is 0, third is 5, next iteration yields i=1, third=8; i=2, third=11; i=3, third=14, etc. -> i will never reach third.
I would improve your code by dropping the entire if-statement, remove third all together and simply increment by 3 in the for-loop:
for( int i = 2; i < str.length(); i+=3){
x += (str.substring(third-1, third+1) +
str.substring(third-2, third-2 + 1));
}
If I am not misinterpreting your code you are missing logic for leaving the last characters alone if they are not part of group of three characters.
If you face such effects take a piece of paper and write down the values of the variables after each line of your code.
The if block creates an alternative execution path if the condition is true which is in every third loop iteration.
Anything behind the if block is executed in every loop iteration.
So when the line in question is inside the if block (before the closing brace) the value in variable third is only changed every third loop iteration.
When you move the line behind the closing brace the assignment is outside the if block and therefore executed every loop iteration.
For the comment = //work with this line but why??????
The value of "third" variable gets changed in the for loop only with i is equal to third character, otherwise the value of third will keep on increasing eg.
when i = 0, third = 2
when i = 1, third = 5
when i = 2, third = 8
so the if statement never gets triggered and hence it doesn't work. Hope this makes sense.
PS - I highly recommend using IDE debugger to understand this properly.
PS - It's better to use charAt method as compared for substring method for performance reason
public String oneTwo(String str) {
String temp = "";
String result = "";
int i = 0;
while (str.substring(i).length() >= 3) {
temp = str.substring(i, i + 3);
result += temp.substring(1) + temp.charAt(0);
i += 3;
}
return result;
}
public String oneTwo(String str) {
String str1 = "";
if(str.length()<3){
return str1;
}else if(str.length()>=3){
for(int i =0; i<str.length()-2; i=i+3){
str1 = str1 + str.substring(i+1,i+3)+ str.substring(i,i+1);
}
}
return str1;
}
public String oneTwo(String str) {
if(str.length()<3)return "";
return str.substring(1,3)+str.substring(0,1)+oneTwo(str.substring(3));
}
this is fairly simple as a recursive problem
public String oneTwo(String str) {
String newThreeChars = "";
if(str.length()<3){
return newThreeChars;
}
for(int i=0; i<str.length()/3; i+=3){
String threeChars = str.substring(i,i+3);
String redesigned = threeChars.substring(1) + threeChars.charAt(0);
newThreeChars +=redesigned;
}
return newThreeChars;
}
Another solution to look at...
public String oneTwo(String str) {
int i = 0;
String result = "";
Character tmpChar = '\0';
while(i <= str.length()-3){
tmpChar = str.charAt(i);
result = result + str.charAt(i+1) + str.charAt(i+2) + tmpChar;
tmpChar = '\0';
i = i + 3;
}
return result;
}
First, We loop through each letter of the given String just stopping shy of the last two letters because the word we are looking for is three letters long. Then, we are returning true if there is two letter "b"'s exactly one character apart.
public boolean bobThere(String str) {
for (int i = 0; i < str.length() - 2; i++) {
if (str.charAt(i) == 'b' && str.charAt(i+2) == 'b')
return true;
}
return false;
}
For string concatenation in a loop use StringBuilder:
public String oneTwo(String str) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length() - 2; i += 3) {
sb.append(str.charAt(i + 1)).append(str.charAt(i + 2)).append(str.charAt(i));
}
return sb.toString();
}

Minimum window in String 1 containing all characters from String 2 and no character from String 3

Ok, this is an interview question. And no it's not a duplicate of this question.
Given 3 strings - str1, str2, str3:
str1 = "spqrstrupvqw"
str2 = "sprt"
str3 = "q"
We've to find the minimum window in str1, which contains all characters from str2 in any order, but no character from str3. In this case the answer would be: "strup".
I've come up with this code:
static String minimumWindow(String str1, String str2, String str3) {
class Window implements Comparable<Window> {
int start;
int end;
public Window(int start, int end) {
this.start = start;
this.end = end;
}
public int getEnd() {
return end;
}
public int getStart() {
return start;
}
public int compareTo(Window o) {
int thisDiff = end - start;
int thatDiff = o.end - o.start;
return Integer.compare(thisDiff, thatDiff);
}
#Override
public String toString() {
return "[" + start + " : " + end + "]";
}
}
// Create Sets of characters for "contains()" check
Set<Character> str2Chars = new HashSet<>();
for (char ch: str2.toCharArray()) {
str2Chars.add(ch);
}
Set<Character> str3Chars = new HashSet<>();
for (char ch: str3.toCharArray()) {
str3Chars.add(ch);
}
// This will store all valid window which doesn't contain characters
// from str3.
Set<Window> set = new TreeSet<>();
int begin = -1;
// This loops gets each pair of index, such that substring from
// [start, end) in each window doesn't contain any characters from str3
for (int i = 0; i < str1.length(); i++) {
if (str3Chars.contains(str1.charAt(i))) {
set.add(new Window(begin, i));
begin = i + 1;
}
}
int minLength = Integer.MAX_VALUE;
String minString = "";
// Iterate over the windows to find minimum length string containing all
// characters from str2
for (Window window: set) {
if ((window.getEnd() - 1 - window.getStart()) < str2.length()) {
continue;
}
for (int i = window.getStart(); i < window.getEnd(); i++) {
if (str2Chars.contains(str1.charAt(i))) {
// Got first character in this window that is in str2
// Start iterating from end to get last character
// [start, end) substring will be the minimum length
// string in this window
for (int j = window.getEnd() - 1; j > i; j--) {
if (str2Chars.contains(str1.charAt(j))) {
String s = str1.substring(i, j + 1);
Set<Character> sChars = new HashSet<>();
for (char ch: s.toCharArray()) {
sChars.add(ch);
}
// If this substring contains all characters from str2,
// then only it is valid window.
if (sChars.containsAll(str2Chars)) {
int len = sChars.size();
if (len < minLength) {
minLength = len;
minString = s;
}
}
}
}
}
}
}
// There are cases when some trailing and leading characters are
// repeated somewhere in the middle. We don't need to include them in the
// minLength.
// In the given example, the actual string would come as - "rstrup", but we
// remove the first "r" safely.
StringBuilder strBuilder = new StringBuilder(minString);
while (strBuilder.length() > 1 && strBuilder.substring(1).contains("" + strBuilder.charAt(0))) {
strBuilder.deleteCharAt(0);
}
while (strBuilder.length() > 1 && strBuilder.substring(0, strBuilder.length() - 1).contains("" + strBuilder.charAt(strBuilder.length() - 1))) {
strBuilder.deleteCharAt(strBuilder.length() - 1);
}
return strBuilder.toString();
}
But it doesn't work for all the test cases. It does work for the example given in this question. But when I submitted the code, it failed for 2 test cases. No I don't know the test cases for which it failed.
Even after trying various sample inputs, I couldn't find a test case for which it fails. Can someone take a look as to what is wrong with the code? I would really appreciate if someone can give a better algorithm (Just in pseudo-code). I know this is really not the optimized solution though.
str1 = "spqrstrupvqw"
str2 = "sprt"
str3 = "q"
We're looking for the minimum sub-string from str1 that contain all str2 characters (assume ordered) and no characters from str3 ..
i = 1 .. str1.length
cursor = 1 .. str2.length
The solution must be on the form:
str2.first X X .. X X str2.last
So to check for that sub-string we use a cursor over str2, but we also have the constraint of avoiding str3 characters, so we have:
if str3.contain(str1[i])
cursor = 1
else
if str1[i] == str2[cursor]
cursor++
Goal check is:
if cursor > str2.length
return solution
else
if i >= str1.length
return not-found
And for optimization, you can skip to the next look-ahead which is:
look-ahead = { str2[cursor] or { X | X in str3 }}
In case str2 is not ordered:
i = 1 .. str1.length
lookup = { X | X in str2 }
The solution must be on the form:
str2[x] X X .. X X str2[x]
So to check for that sub-string we use a check-list str2, but we also have the constraint of avoiding str3 characters, so we have:
if str3.contain(str1[i])
lookup = { X | X in str2 }
else
if lookup.contain(str1[i])
lookup.remove(str1[i])
Goal check is:
if lookup is empty
return solution
else
if i >= str1.length
return not-found
And for optimization, you can skip to the next look-ahead which is:
look-ahead = {{ X | X in lookup } or { X | X in str3 }}
Code
class Solution
{
private static ArrayList<Character> getCharList (String str)
{
return Arrays.asList(str.getCharArray());
}
private static void findFirst (String a, String b, String c)
{
int cursor = 0;
int start = -1;
int end = -1;
ArrayList<Character> stream = getCharList(a);
ArrayList<Character> lookup = getCharList(b);
ArrayList<Character> avoid = getCharList(c);
for(Character ch : stream)
{
if (avoid.contains(ch))
{
lookup = getCharList(b);
start = -1;
end = -1;
}
else
{
if (lookup.contains(ch))
{
lookup.remove(ch)
if (start == -1) start = cursor;
end = cursor;
}
}
if (lookup.isEmpty())
break;
cursor++;
}
if (lookup.isEmpty())
{
System.out.println(" found at ("+start+":"+end+") ");
}
else
{
System.out.println(" not found ");
}
}
}
Here is working Java code tested on various test cases.
The algorithm basically uses a sliding window to examine different windows within which an answer may lie. Each character in the string str2 is analyzed at most twice. Thus the running time of the algorithm is linear, ie O(N) in the lengths of the three strings. This is infact the most optimal solution for this problem.
String str1 = "spqrstrupvqw";
String str2 = "sprt";
String str3 = "q";
char[] arr = str1.toCharArray();
HashSet<Character> take = new HashSet<Character>();
HashSet<Character> notTake = new HashSet<Character>();
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
void run()throws java.lang.Exception{
System.out.println(str1 + " " + str2 + " " + str3);
//Add chars of str2 to a set to check if a char has to be taken in O(1)time.
for(int i=0; i<str2.length(); i++){
take.add(str2.charAt(i));
}
//Add chars of str3 to a set to check if a char shouldn't be taken in O(1) time.
for(int i=0; i<str3.length(); i++){
notTake.add(str3.charAt(i));
}
int last = -1;
int bestStart = -1;
int bestLength = arr.length+1;
// The window will be from [last....next]
for(int next=last+1; next<arr.length; next++){
if(notTake.contains(arr[next])){
last = initLast(next+1); //reinitialize the window's start.
next = last;
}else if(take.contains(arr[next])){
// take this character in the window and update count in map.
if(last == -1){
last = next;
map.put(arr[last], 1);
}else{
if(!map.containsKey(arr[next])) map.put(arr[next], 1);
else map.put(arr[next], map.get(arr[next])+1);
}
}
if(last >= arr.length){ // If window is invalid
break;
}
if(last==-1){
continue;
}
//shorten window by removing chars from start that are already present.
while(last <= next){
char begin = arr[last];
// character is not needed in the window, ie not in set "take"
if(!map.containsKey(begin)){
last++;
continue;
}
// if this character already occurs in a later part of the window
if(map.get(begin) > 1){
last++;
map.put(begin, map.get(begin)-1);
}else{
break;
}
}
// if all chars of str2 are in window and no char of str3 in window,
// then update bestAnswer
if(map.size() == str2.length()){
int curLength = next - last + 1;
if(curLength < bestLength){
bestLength = curLength;
bestStart = last;
}
}
}
if(bestStart==-1){
System.out.println("there is no such window");
}else{
System.out.println("the window is from " + bestStart + " to " + (bestStart + bestLength-1));
System.out.println("window " + str1.substring(bestStart, bestStart+bestLength));
}
}
// Returns the first position in arr starting from index 'fromIndex'
// such that the character at that position is in str2.
int initLast(int fromIndex){
// clear previous mappings as we are starting a new window
map.clear();
for(int last=fromIndex; last<arr.length; last++){
if(take.contains(arr[last])){
map.put(arr[last], 1);
return last;
}
}
return arr.length;
}
Moreover, your code fails on many trivial test cases. One of them is when str1 = "abc", str2 = "ab", str3 = "c".
PS. If you are having a hard time understanding this code, first try reading this easier post which is very similar to the problem that has been asked.
What about using a regular expression?
String regex = ".*((?=[^q]*s)(?=[^q]*p)(?=[^q]*r)(?=[^q]*t)[sprt][^q]+([sprt])(?<!ss|pp|rr|tt))";
Matcher m = Pattern.compile(regex).matcher("spqrstrupvqw");
while (m.find()) {
System.out.println(m.group(1));
}
This prints out:
strup
This can also be wrapped in a method which generates dynamically the regular expression for variable inputs:
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatchString {
public static void main(String[] args) {
System.out.println(getMinimalSubstrings("spqrstrupvqw", "sprt", "q"));
System.out.println(getMinimalSubstrings("A question should go inside quotations.", "qtu", "op"));
System.out.println(getMinimalSubstrings("agfbciuybfac", "abc", "xy"));
}
private static List<String> getMinimalSubstrings(String input, String mandatoryChars, String exceptChars) {
List<String> list = new ArrayList<String>();
String regex = buildRegEx(mandatoryChars, exceptChars);
Matcher m = Pattern.compile(regex).matcher(input);
while (m.find()) {
list.add(m.group(1));
}
return list;
}
private static String buildRegEx(String mandatoryChars, String exceptChars) {
char[] mandChars = mandatoryChars.toCharArray();
StringBuilder regex = new StringBuilder("[^").append(exceptChars).append("]*(");
for (char c : mandChars) {
regex.append("(?=[^").append(exceptChars).append("]*").append(c).append(")");
}
regex.append("[").append(mandatoryChars).append("][^").append(exceptChars).append("]+([").append(mandatoryChars).append("])(?<!");
for (int i = 0; i < mandChars.length; i++) {
if (i > 0) {
regex.append("|");
}
regex.append(mandChars[i]).append(mandChars[i]);
}
regex.append("))");
return regex.toString();
}
}
This prints out:
[strup]
[quest]
[agfbc, bfac]

Finding Anagrams with vowels always at the end

I was trying out this question :
Write a function using Recursion to display all anagrams of a string entered by the user, in such a way that all its vowels are located at the end of every anagram. (E.g.: Recursion => Rcrsneuio, cRsnroieu, etc.) Optimize it.
From this site :
http://erwnerve.tripod.com/prog/recursion/magic.htm
This is what i have done :
public static void permute(char[] pre,char[] suff) {
if (isEmpty(suff)) {
//result is a set of string. toString() method will return String representation of the array.
result.add(toString(moveVowelstoEnd(pre)));
return;
}
int sufflen = getLength(suff); //gets the length of the array
for(int i =0;i<sufflen;i++) {
char[] tempPre = pre.clone();
char[] tempSuf = suff.clone();
int nextindex = getNextIndex(pre); //find the next empty spot in the prefix array
tempPre[nextindex] = tempSuf[i];
tempSuf = removeElement(i,tempSuf); //removes the element at i and shifts array to the left
permute(tempPre,tempSuf);
}
}
public static char[] moveVowelstoEnd(char[] input) {
int c = 0;
for(int i =0;i<input.length;i++) {
if(c>=input.length)
break;
char ch = input[i];
if (vowels.contains(ch+"")) {
c++;
int j = i;
for(;j<input.length-1;j++)
input[j] = input[j+1];
input[j]=ch;
i--;
}
}
return input;
}
Last part of the question is 'Optimize it'. I am not sure how to optimize this. can any one help?
Group all the vowels into v
Group all consonants into w
For every pair of anagrams, concat the results

Categories