Sub-sequence of Vowels

廉价感情. 提交于 2019-12-04 22:41:35

问题


I was practicing for an interview and came across this question on a website:

A magical sub-sequence of a string S is a sub-sequence of S that contains all five vowels in order. Find the length of largest magical sub-sequence of a string S.

For example, if S = aeeiooua, then aeiou and aeeioou are magical sub-sequences but aeio and aeeioua are not.

I am a beginner in dynamic programming and am finding it hard to come up with a recursive formula for this.


回答1:


I did it with an iterative approach rather than recursive one. I started building solution similar to LIS (Longest Increasing Subsequence) and then optimised it upto O(n).

#include<iostream>
#include<string>
#include<vector>
using namespace std;

string vowel = "aeiou";

int vpos(char c)
{
    for (int i = 0; i < 5; ++i)
        if (c == vowel[i])
            return i;
    return -1;
}

int magical(string s)
{
    int l = s.length();
    int previndex[5] = {-1, -1, -1, -1, -1};    // for each vowel
    vector<int> len (l, 0);
    int i = 0, maxlen = 0;

    // finding first 'a'
    while (s[i] != 'a')
    {
        ++i;
        if (i == l)
            return 0;
    }

    previndex[0] = i;       //prev index of 'a'
    len[i] = 1;

    for ( ++i; i < l; ++i)
    {
        if (vpos(s[i]) >= 0)    // a vowel
        {
            /* Need to append to longest subsequence on its left, only for this vowel (for any vowels) and 
             * its previous vowel (if it is not 'a')
                This important observation makes it O(n) -- differnet from typical LIS
            */
            if (previndex[vpos(s[i])] >= 0)
                len[i] = 1+len[previndex[vpos(s[i])]];

            previndex[vpos(s[i])] = i;

            if (s[i] != 'a')
            {
                if (previndex[vpos(s[i])-1] >= 0)
                    len[i] = max(len[i], 1+len[previndex[vpos(s[i])-1]]);
            }

            maxlen = max(maxlen, len[i]);
        }
    }
    return maxlen;
}

int main()
{
    string s = "aaejkioou";
    cout << magical(s);
    return 0;
}



回答2:


O(input string length) runtime import java.util.*;

public class Main {
    /*
        algo:
        keep map of runningLongestSubsequence that ends in each letter. loop through String s. for each char, try appending
        to runningLongestSubsequence for that char, as well as to runningLongestSubsequence for preceding char.
        update map with whichever results in longer subsequence.

        for String s = "ieaeiouiaooeeeaaeiou", final map is:
        terminal letter in longest running subsequence-> longest running subsequence
        a -> aaaa
        e -> aeeeee
        i -> aeeeeei
        o -> aeeeeeio
        u -> aeeeeeiou

        naming:
        precCharMap - precedingCharMap
        runningLongestSubMap - runningLongestSubsequenceMap
     */

    public static int longestSubsequence(String s) {

        if (s.length() <= 0) throw new IllegalArgumentException();

        Map<Character, Character> precCharMap = new HashMap<>();
        precCharMap.put('u', 'o');
        precCharMap.put('o', 'i');
        precCharMap.put('i', 'e');
        precCharMap.put('e', 'a');

        Map<Character, String> runningLongestSubMap = new HashMap<>();

        for (char currChar : s.toCharArray()) {
            //get longest subs
            String currCharLongestSub;
            String precCharLongestSub = null;
            if (currChar == 'a') {
                currCharLongestSub = runningLongestSubMap.getOrDefault(currChar, "");
            } else {
                currCharLongestSub = runningLongestSubMap.get(currChar);
                char precChar = precCharMap.get(currChar);
                precCharLongestSub = runningLongestSubMap.get(precChar);
            }

            //update running longest subsequence map
            if (precCharLongestSub == null && currCharLongestSub != null) {
                updateRunningLongestSubMap(currCharLongestSub, currChar, runningLongestSubMap);
            } else if (currCharLongestSub == null && precCharLongestSub != null) {
                updateRunningLongestSubMap(precCharLongestSub, currChar, runningLongestSubMap);
            } else if (currCharLongestSub != null && precCharLongestSub != null) {
                //pick longer
                if (currCharLongestSub.length() < precCharLongestSub.length()) {
                    updateRunningLongestSubMap(precCharLongestSub, currChar, runningLongestSubMap);
                } else {
                    updateRunningLongestSubMap(currCharLongestSub, currChar, runningLongestSubMap);
                }
            }
        }

        if (runningLongestSubMap.get('u') == null) {
            return 0;
        }
        return runningLongestSubMap.get('u').length();
    }

    private static void updateRunningLongestSubMap(String longestSub, char currChar,
                                                   Map<Character, String> runningLongestSubMap) {
        String currCharLongestSub = longestSub + currChar;
        runningLongestSubMap.put(currChar, currCharLongestSub);
    }

    public static void main(String[] args) {
        //String s = "aeeiooua"; //7
        //String s = "aeiaaioooaauuaeiou"; //10
        String s = "ieaeiouiaooeeeaaeiou"; //9
        //String s = "ieaeou"; //0
        //String s = "ieaeoooo"; //0
        //String s = "aeiou"; //5
        //if u have String s beginning in "ao", it'll do nothing with o and 
        //continue on to index 2.

        System.out.println(longestSubsequence(s));
    }
}



回答3:


#include <iostream>
#include<string>
#include<cstring>

using namespace std;
unsigned int getcount(string a, unsigned int l,unsigned int r );
int main()
{    
    std::string a("aaaaaeeeeaaaaiiioooeeeeuuuuuuiiiiiaaaaaaoo"
                 "oooeeeeiiioooouuuu");
    //std::string a("aaaaaeeeeaaaaiiioooeeeeuuuuuuiiiiiaaaaaaoooooeeeeiiioooo"); 
   //std::string a("aaaaaeeeeaaaaiiioooeeeeiiiiiaaaaaaoooooeeeeiiioooo"); //sol0
  //std::string a{"aeiou"};
  unsigned int len = a.length();
  unsigned int i=0,cnt =0,countmax =0;
  bool newstring = true;
  while(i<len)
  {
      if(a.at(i) == 'a' && newstring == true) 
      {
          newstring = false;
          cnt = getcount(a,i,len);
          if(cnt > countmax) 
          {
             countmax = cnt;
             cnt = 0;
          }
        } 
        else if(a.at(i)!='a')
        {
            newstring = true;
        }
        i++;
    }
    cout<<countmax;
    return 0;
}

unsigned int getcount(string a, unsigned int l,unsigned int r )
{
    std::string b("aeiou");
    unsigned int seq=0,cnt =0;
    unsigned int current =l;
    bool compstr = false;
    while(current<r)
    {
        if(a.at(current) == b.at(seq)) 
        {
            cnt++;
        }
        else if((seq <= (b.size()-2)) && (a.at(current) == b.at(seq+1)))
        {
            seq++; 
            cnt++;
            if (seq == 4) 
                compstr =true;
        }
        current++;
    }
    if (compstr == true) 
        return cnt;
   return 0;
}



回答4:


you can use recursive approach here (this should work for string length upto max int (easily memorization can be used)

public class LMV {

static final int NOT_POSSIBLE = -1000000000;
// if out put is this i.e soln not possible 


static int longestSubsequence(String s, char[] c) {

    //exit conditions
    if(s.length() ==0 || c.length ==0){
        return 0;
    }

    if(s.length() < c.length){
        return NOT_POSSIBLE;
    }

    if(s.length() == c.length){
        for(int i=0; i<s.length(); i++){
            if(s.charAt(i) !=c [i]){
                return NOT_POSSIBLE;
            }
        }
        return s.length();
    }

    if(s.charAt(0) < c[0]){
        // ignore, go ahead with next item
        return longestSubsequence(s.substring(1), c);
    } else if (s.charAt(0) == c[0]){
        // <case 1> include item and start search for next item in chars
        // <case 2> include but search for same item again in chars
        // <case 3> don't include item

        return Math.max(
                Math.max(  ( 1+longestSubsequence(s.substring(1), Arrays.copyOfRange(c, 1, c.length) ) ),
                            ( 1+longestSubsequence(s.substring(1), c ) ) ),
                ( longestSubsequence(s.substring(1), c )) );
    } else {
        //ignore
        return longestSubsequence(s.substring(1), c);
    }
}



public static void main(String[] args) {

    char[] chars = {'a', 'e', 'i', 'o', 'u'};

    String s1 = "aeio";
    String s2 = "aaeeieou";
    String s3 = "aaeeeieiioiiouu";

    System.out.println(longestSubsequence(s1, chars));
    System.out.println(longestSubsequence(s2, chars));
    System.out.println(longestSubsequence(s3, chars));

}

}




回答5:


Here's a python code for your question. Did it using a non-recursive approach.

Picked from my repository here: MagicVowels Madaditya

############################################################################
#
# Magical Subsequence of  Vowels
#       by Aditya Kothari (https://github.com/Madaditya/magivvowels)
#
#
############################################################################
import sys
import re

usage = '''
Error : Invalid no of arguments passed.
Usage :
python magicv.py string_to_check
eg: python magicv.py aaeeiiooadasduu
'''

def checkMagicVowel(input_string):
    #The Answer Variable 
    counter = 0

    #Check if all vowels exist
    if ('a' in input_string) and ('e' in input_string) and ('i' in input_string) and ('o' in input_string) and ('u' in input_string):

        vowel_string = 'aeiou'
        input_string_voweslOnly = ''

        #Keeping only vowels in the string i.e user string MINUS NON vowels
        for letter in input_string:
            if letter in 'aeiou':
                input_string_voweslOnly = input_string_voweslOnly + letter

        magic = ''
        index_on_vowel_string = 0
        current_vowel = vowel_string[index_on_vowel_string]
        #i is index on the current Character besing tested
        i = 0
        for current_char in input_string_voweslOnly:

            if current_char == current_vowel:
                counter = counter + 1
                magic = magic + current_char

            if (i < len(input_string_voweslOnly)-1):
                next_char = input_string_voweslOnly[i+1]

                if(index_on_vowel_string != 4):
                    next_vowel = vowel_string[index_on_vowel_string+1]
                else:
                    next_vowel = vowel_string[index_on_vowel_string]

                #next character should be the next new vowel only to count++
                if (current_char != next_char and next_char == next_vowel):
                        if(index_on_vowel_string != 4):
                            index_on_vowel_string = index_on_vowel_string + 1
                        current_vowel = vowel_string[index_on_vowel_string]

            i = i + 1
        #Uncomment next line to print the all magic sequences
        #print magic

        '''
        #Regex Method
        #magic = re.match('[a]+[e]+[i]+[o]+[u]+',input_string_voweslOnly)
        magic = re.match('[aeiou]+',input_string_voweslOnly)
        if magic is not None:
            ##print magic.group() 
            ##print len(magic.group())
        else:
            ##print(0)
        '''
    else:
        counter = 0
    return counter

if __name__ == "__main__":

    #checking arguments passed
    if(len(sys.argv) != 2):
        print usage
        sys.exit(0)
    input_string = sys.argv[1].lower()

    #get all possible substrings
    all_a_indices = [i for i, ltr in enumerate(input_string) if ltr == 'a']
    substrings = []
    for item in all_a_indices:
        substrings.append(input_string[item:])
    #print substrings

    #Pass each substring and find the longest magic one
    answer = []
    for each in substrings:
        answer.append(checkMagicVowel(each))
    print max(answer)



回答6:


int func( char *p)
{
    char *temp = p;
    char ae[] = {'a','e','i','o','u'};

    int size = strlen(p), i = 0;
    int chari = 0, count_aeiou=0;
    for (i=0;i<=size; i++){
        if (temp[i] == ae[chari]) {
            count_aeiou++;
        }
        else if ( temp[i] == ae[chari+1]) {
            count_aeiou++;
            chari++;
        }
    }
    if (chari == 4 ) {
        printf ("Final count : %d ", count_aeiou);
    } else {
        count_aeiou = 0;
    }
    return count_aeiou;
}

The solution to retrun the VOWELS count as per the hackerrank challenge.




回答7:


int findsubwithcontinuousvowel(string str){
    int curr=0;
    int start=0,len=0,maxlen=0,i=0;
    for(i=0;i<str.size();i++){
        if(str[i]=='u' && (current[curr]=='u' ||  (curr+1<5 && current[curr+1]=='u'))){
           //len++;
           maxlen=max(len+1,maxlen);
        }

        if(str[i]==current[curr]){
            len++;
        }
        else if(curr+1<5 && str[i]==current[curr+1]){
            len++;
            curr++;
        }
        else{
            len=0;
            curr=0;
            if(str[i]=='a'){
                len=1;
            }
        }
    }
    return maxlen;
}



回答8:


Check if vowels are available in sequence in isInSequence and process the result on processor.

public class one {

private char[] chars = {'a','e','i','o','u'};
private int a = 0;

private boolean isInSequence(char c){
    // check if char is repeating
    if (c == chars[a]){
        return true;
    }
    // if vowels are in sequence and just passed by 'a' and so on...
    if (c == 'e' && a == 0){
        a++;
        return true;
    }
    if (c == 'i' && a == 1){
        a++;
        return true;
    }
    if (c == 'o' && a == 2){
        a++;
        return true;
    }
    if (c == 'u' && a == 3){
        a++;
        return true;
    }
    return false;
}

private char[] processor(char[] arr){
    int length = arr.length-1;
    int start = 0;
    // In case if all chars are vowels, keeping length == arr
    char array[] = new char[length];

    for (char a : arr){
        if (isInSequence(a)){
            array[start] = a;
            start++;
        }
    }
    return array;
}

public static void main(String args[]){
    char[] arr = {'m','a','e','l','x','o','i','o','u','a'};
    one o = new one();
    System.out.print(o.processor(arr));
 }
}



回答9:


#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(NULL);cin.tie(NULL);cout.tie(NULL);
#define ll unsigned long long
using namespace std;

int main() {
    // your code goes here
 ios
string s;
cin>>s;
int n=s.length();
int dp[n+1][5]={0};
for(int i=1;i<=n;i++)
{
    if(s[i-1]=='a')
    {
        dp[i][0]=1+dp[i-1][0];
        dp[i][1]=dp[i-1][1];
        dp[i][2]=dp[i-1][2];
        dp[i][3]=dp[i-1][3];
        dp[i][4]=dp[i-1][4];
    }
    else if(s[i-1]=='e')
    {dp[i][0]=dp[i-1][0];
    if(dp[i-1][0]>0)
        {dp[i][1]=1+max(dp[i-1][1],dp[i-1][0]);}
        else
        dp[i-1][1]=0;
        dp[i][2]=dp[i-1][2];
        dp[i][3]=dp[i-1][3];
        dp[i][4]=dp[i-1][4];
    }
     else if(s[i-1]=='i')
    {dp[i][0]=dp[i-1][0];
    if(dp[i-1][1]>0)
        {dp[i][2]=1+max(dp[i-1][1],dp[i-1][2]);}
        else
        dp[i-1][2]=0;
        dp[i][1]=dp[i-1][1];
        dp[i][3]=dp[i-1][3];
        dp[i][4]=dp[i-1][4];
    }
    else if(s[i-1]=='o')
    {dp[i][0]=dp[i-1][0];
    if(dp[i-1][2]>0)
        {dp[i][3]=1+max(dp[i-1][3],dp[i-1][2]);}
        else
        dp[i-1][3]=0;
        dp[i][2]=dp[i-1][2];
        dp[i][1]=dp[i-1][1];
        dp[i][4]=dp[i-1][4];
    }
    else if(s[i-1]=='u')
    {dp[i][0]=dp[i-1][0];
       if(dp[i-1][3]>0)
        {dp[i][4]=1+max(dp[i-1][4],dp[i-1][3]);}
        else
        dp[i-1][4]=0;
        dp[i][1]=dp[i-1][1];
        dp[i][3]=dp[i-1][3];
        dp[i][2]=dp[i-1][2];
    }
    else
    {
        dp[i][0]=dp[i-1][0];
        dp[i][1]=dp[i-1][1];
        dp[i][2]=dp[i-1][2];
        dp[i][3]=dp[i-1][3];
        dp[i][4]=dp[i-1][4];
    }


}
cout<<dp[n][4];


return 0;
}


来源:https://stackoverflow.com/questions/44554450/sub-sequence-of-vowels

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!