3

Given a string made up of 'a' and 'b' only,the operation that is allowed is to remove a substring of "abb" if present from the string. My question is after applying this operation any no of times can i make the string empty. I need a O(n) algorithm.

Example , abbabb-->yes

aabbbb->yes since aabbbb->abb->empty

aaabbb->no since aaabbb->aab

All that i can think upto now is an O(n^2) algorithm in which i sucessively find the position of the substring using substr() or find() and then remove it until string not empty or not found a "abb" in it.

4 Answers4

3

Here is an example of what I suggested in the comment:

for i = 0 to word.length-1
    if word[i] == 'b'
        if stack.empty() //no corresponding a
            return false
        if stack.top() == 'a' //first b after an a
            stack.push('b')
        else                  //second b after an a
            stack.pop()       //pop last two letters
            stack.pop()
    else
        stack.push('a')
return stack.empty()

There might be some boundary conditions that needs to be checked, and of course at any point pop() fails you need to return false. Seems to be working for the possible inputs that occurs to me.

The point that needs to be mathematically proved, I think, is the part where I commented "second b after an a". With the assumption that stack was empty at the beginning, if I did not miss anything that point looks correct.

2

It is not necessary to store anything but the count of unused pairs of b's at the end of the string, as you read it Right to Left. (And it's solved reading input only once, so O(n) time O(1) space) This is very reminiscent of finding a discrete finite automata for a regular language. If you see two b's, increase count. If you see a single b, add half a pair (update a boolean variable and possibly increment count). If you see an a and have no pair of b's, fail, else count--. If you reach the end of the string and there were no extra b's, the string was valid.

clwhisk
  • 1,805
  • 1
  • 18
  • 17
1

Make use of two counters to avoid using stack. Here is the c++ implementaion hope it works.

bool canBeDone(string s)
{
int aCount = 0;
int bCount = 0;
for(int i=0;i<s.length();++i)
{
    if(s[i] == 'a')
    {
        aCount++;
        continue;
    }
    if(s[i] == 'b' && aCount == 0)
        return false;
    else
    {
        bCount += 1;
        if(bCount == 2)
        {
            bCount = 0;
            aCount--;
        }
    }
}
if(!aCount && !bCount)return true;
return false;
}
venkatvb
  • 681
  • 1
  • 9
  • 24
0

Very simple and straightforward implementation in Erlang O(n) space and time (unfortunately even clwhisk's algorithm needs O(n) space in Erlang because of lists:reverse/1):

-module(abb).

-export([check/1, clwhisk/1, test/0]).

check(L) when is_list(L) ->
    check(L, []).

check(L, "bba" ++ T) -> check(L, T);
check([H|T], S) -> check(T, [H|S]);
check([], S) -> S =:= [].

clwhisk(L) when is_list(L) ->
    clwhisk(lists:reverse(L), 0).

clwhisk([$b|T], C) -> clwhisk(T, C+1);
clwhisk([$a|T], C) -> C >= 2 andalso clwhisk(T, C-2);
clwhisk(L, C) -> L =:= [] andalso C =:= 0.

test() ->
    true = abb:check("abbabb"),
    true = abb:check("aabbbb"),
    false = abb:check("aaabbb"),
    true = abb:check("ababbb"),
    true = abb:clwhisk("abbabb"),
    true = abb:clwhisk("aabbbb"),
    false = abb:clwhisk("aaabbb"),
    true = abb:clwhisk("ababbb"),
    ok.

And there is C implementation of clwhisk's algorithm as filter:

#include <stdlib.h>
#include <stdio.h>

static inline const char *last(const char* s){
    for(;*s && *s!='\n';s++);
    return s-1;
}

static int check(const char* s){
    int count=0;
    const char *ptr = last(s);
    for(; ptr >= s; ptr--)
        if(*ptr == 'b') {
            count++;
        }
        else if(*ptr == 'a') {
            count -= 2;
            if(count < 0)
                return 0;
        }
        else return 0;
    return count == 0;
}

int main(void) {
    char *line = NULL;
    size_t len = 0;
    while( getline(&line, &len, stdin) != -1 )
        if(*line && *line != '\n' && check(line))
            fputs(line, stdout);
    return EXIT_SUCCESS;
}
Community
  • 1
  • 1
Hynek -Pichi- Vychodil
  • 26,174
  • 5
  • 52
  • 73