Q:

Algorithm that spits out the smallest and largest substring starting with vowel and ending with consonant for a String

I am trying to write such an algorithm in Java. I am testing the String input "abaab". It's safe to assume the string inputs will be lowercase.
I am at a loss in checking where my algorithm is going wrong (it only outputs "a a" for this input instead of "ab" and "abaab". Any ideas?
static void SmallestAndLargestSubstring(String input) {

        char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
        char[] cons = { 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x',
                'y', 'z' };
        char[] charArray = input.toLowerCase().toCharArray();
        int startIndex = 0;
        int shortEndIndex = 0;
        int longEndIndex = 0;
        int large = longEndIndex - startIndex;
        int small = shortEndIndex - startIndex;
        ArrayList<Integer> start = new ArrayList<Integer>();
        ArrayList<Integer> end = new ArrayList<Integer>();

        outerloop: for (int i = 0; i < charArray.length; i++) {
            for (int z = 0; z < vowels.length; z++) {
                if (charArray[i] == vowels[z]) {
                    startIndex = i;
                    start.add(startIndex);
                    if (longEndIndex - startIndex > large) {
                        large = longEndIndex - startIndex;                  
                    }
                    if(longEndIndex - startIndex <= large){
                        shortEndIndex=start.get(start.size()-1);
                    }
                    if (shortEndIndex - startIndex < small) {
                        small = shortEndIndex - startIndex; 
                    }
                    if(shortEndIndex - startIndex >=small){
                        shortEndIndex=start.get(start.size()-1);
                    }

                    continue outerloop;
                }
            }
            for (int j = 0; j < cons.length; j++) {
                if (charArray[i] == cons[j]) {  
                    longEndIndex = i;
                    shortEndIndex = i;
                    end.add(longEndIndex);
                    if (longEndIndex - startIndex > large) {
                        large = longEndIndex - startIndex;
                    }if(longEndIndex - startIndex <= large){
                        longEndIndex=end.get(end.size()-1);
                    }
                    if (shortEndIndex - startIndex < small) {
                        small = shortEndIndex - startIndex;                     
                    }               
                    if(shortEndIndex - startIndex >=small) {
                        shortEndIndex=end.get(end.size()-1);
                    }
                    continue outerloop;
                }
            }
        }

        System.out.println(input.substring(startIndex, shortEndIndex));
        System.out.println(input.substring(startIndex, longEndIndex));
    }

A:

I stumbled upon this question searching for the same problem.

THE CURRENTLY ACCEPTED ANSWER IS WRONG.

For string uauubbiox, the program in the accepted answer outputs:
ub
uauubbiox

which is wrong (correct answer is auub and uubbiox.) Even for the case in the OP's question, this program gives the wrong answer (abaab instead of baab).
The correct way to approach this problem is to use suffix arrays. Here is a pseudo code that I believe will yield the correct output for this problem:
given string s as input
sa = suffix_array(s)
savf = the first string in sa which starts with a vowel
smallest substring = savf.substring(0, index of first consonant)

savl = the last string in sa which starts with a vowel
smallest substring = savf.substring(0, index of lastconsonant)

Let's try this for the test string. The suffix array for the test string is:
0 auubbiox
1 bbiox
2 biox
3 iox
4 ox
5 uauubbiox
6 ubbiox
7 uubbiox

The smallest lexicographic string starting with a vowel is:
auubbiox

We only need to find the smallest prefix in this string ending with a consonant. That will be the b at position 3 of the above string. Therefore, the lexicographically smallest string starting with a vowel and ending with a consonant is:
auub

For the other string, look at the largest string in suffix array starting with a vowel. That is string at index 7:
uubbiox

Since we want the largest possible string, we should chooose the longest possible prefix ending in a consonant. In this case, that will be the whole above string. Therefore the lexicographically largest string starting with a vowel and ending with a consonant is:
uubbiox

Calculating the suffix array of a string can be done in O(n). The Wikipedia article discusses some of the methods for constructing it. There are also clever techniques on the Internet that make creating one relatively easy to code and implement. I like this one which gives the suffix array with a very stratightforward and easy-to-understand technique with an acceptable (for most cases) time complexiy of O(nlog^2(n))

A:

Here is my solution : the longest substring always start with the first vowel and end with the last consonant.
For the shortest, every time I read a consonant, I look at the distance to the previous vowel and see if it is better.
You can't do anything until you read at least one vowel.
    static void SmallestAndLargestSubstring(String input) {

    char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
    char[] cons = { 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x',
            'y', 'z' };
    char[] charArray = input.toLowerCase().toCharArray();
    int longStartIndex=0;
    int shortStartIndex=0;
    int shortEndIndex=0;
    int longEndIndex=0;
    boolean findVowel = false;
    int bestStart = 0;
    int bestEnd = 0;
    int shortest =Integer.MAX_VALUE;

    for (int i = 0; i < charArray.length; i++) {
        for (int z = 0; z < vowels.length; z++) {
            if (charArray[i] == vowels[z]) {
                if (!findVowel){
                    // if this is the first vowel we see
                    longStartIndex = i;
                    shortStartIndex=i;
                    findVowel = true;
                }
                else {
                     shortStartIndex = i;
                }
            }
        }
        for (int j = 0; j < cons.length; j++) {
            if (charArray[i] == cons[j]) { 
                if (findVowel){
                    // if we have seen any vowel, this consonant is useless
                    longEndIndex = i; // this one is always than the previous for the largest 
                    shortEndIndex = i; // we have to check if this one is better or not
                    if (shortEndIndex-shortStartIndex<shortest){
                         bestStart = shortStartIndex;
                         bestEnd = shortEndIndex;
                         shortest = shortEndIndex-shortStartIndex;
                    }
                }
            }
        }
    }
    System.out.println(input.substring(bestStart, bestEnd+1));
    System.out.println(input.substring(longStartIndex, longEndIndex+1));
}

