web-dev-qa-db-fra.com

Sous-séquence des voyelles

Je pratiquais pour une entrevue et suis tombé sur cette question sur un site web: 

Une sous-séquence magique d'une chaîne S est une sous-séquence de S que contient les cinq voyelles dans l'ordre. Trouvez la longueur de la plus grande sous-séquence magique d'une chaîne S

Par exemple, si S = aeeiooua, aeiou et aeeioou sont des sous-séquences magiques. mais aeio et aeeioua ne le sont pas.

Je suis un débutant en programmation dynamique et j'ai du mal à trouver une formule récursive pour cela. 

6
Arun

Je l'ai fait avec une approche itérative plutôt que récursive. J'ai commencé à construire une solution similaire à LIS (la plus longue augmentation de sous-séquence) puis à l'optimiser jusqu'à 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;
}
4
G_S

O (longueur de la chaîne d'entrée) runtime importer 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));
    }
}
2
Modelday
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;
}
0
Satyendra Kumar
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;
}

La solution pour retourner les VOWELS compte selon le défi du hackerrank.

0
goodies

Vérifiez si les voyelles sont disponibles en séquence dans isInSequence et traitez le résultat dans 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));
 }
}
0
W4R10CK
#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;
}

vous pouvez utiliser ici une approche récursive (cela devrait fonctionner pour une longueur de chaîne allant jusqu'à max int (la mémorisation peut être utilisée facilement)

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));

}

}

0
Ravi Verma
#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;
}
0
Kiran

Voici un code python pour votre question .

Choisi dans mon référentiel ici: 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 __== "__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)
0
Madaditya