私は面接の練習をしていて、ウェブサイトでこの質問に出くわしました。
文字列
S
の魔法のサブシーケンスは、5つの母音すべてを順番に含むS
のサブシーケンスです。文字列S
の最大の魔法のサブシーケンスの長さを見つけます。たとえば、if
S = aeeiooua
、次にaeiou
とaeeioou
は魔法のサブシーケンスですが、aeio
とaeeioua
はそうではありません。
私は動的計画法の初心者であり、このための再帰的な式を思い付くのは難しいと感じています。
私は再帰的なアプローチではなく、反復的なアプローチでそれを行いました。 LIS(Longest Increasing Subsequence)と同様のソリューションの構築を開始し、それを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;
}
O(入力文字列の長さ)ランタイムインポート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));
}
}
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;
}
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;
}
ハッカーランクチャレンジに従ってVOWELSカウントを返すソリューション。
母音がisInSequence
で順番に使用できるかどうかを確認し、結果を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));
}
}
#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;
}
ここでは再帰的アプローチを使用できます(これは最大intまでの文字列長で機能するはずです(簡単に記憶を使用できます)
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));
}
}
#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;
}
これがあなたの質問のpythonコードです。非再帰的アプローチを使用しました。
ここで私のリポジトリから選択: 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)