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 ofS
that contains all five vowels in order. Find the length of largest magical sub-sequence of a stringS
.For example, if
S = aeeiooua
, thenaeiou
andaeeioou
are magical sub-sequences butaeio
andaeeioua
are not.
I am a beginner in dynamic programming and am finding it hard to come up with a recursive formula for this.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With