From: bart.c on

"mohangupta13" <mohangupta13(a)gmail.com> wrote in message
news:2964019b-3f82-4c28-833f-d3752f3eb75f(a)h37g2000pra.googlegroups.com...
> Problem: Given two strings S1 & S2 , return the common elements in
> both the strings ??
>
> One way I thought is to take a b-bit vector ( assuming the range of
> elements in the strings is 0-b) ...now in the first pass through the
> string S1 set all those bit positions that have an element equal to
> them . i.e set i'th bit if we an element with value i..
> Now go through S2 and and AND the i'th bit if we have an element equal
> to i. Now return the elements for which we have a bit set.
>
> Now there are various problems with this 1) It assumes elements in the
> range 0-b .2) It just returns one instance of the common element .i.e
> if S1= AABCA and S2= AAABCBA o/p= ABC and not AAABC .
>
> Can anyone please provide a better way to do this ( in possibly linear
> time and as small space as possible)...??

If by better you mean, generating the right output, I used this:

s1:="AABCA"
s2:="AAABCBA"

hist1:=hist2:=(0,)*256 #ie. histograms

foreach c in s1 do ++hist1[asc(c)] od
foreach c in s2 do ++hist2[asc(c)] od

s3:=""
for i:='A' to 'Z' do # or 0 to 255
if hist1[i] and hist2[i] then
s3+ := chr(i)*(hist1[i] min hist2[i])
fi
od

println "S1=",s1
println "S2=",s2
println "S3=",s3

(The if-statement is not essential, as "A"*0 is "", but is kept for
clarity.)

The process is linear I think, but requires two vectors of 256 (or perhaps
26, depending on your strings) elements.

--
Bartc

From: mohangupta13 on
On 30 Apr, 14:54, "bart.c" <ba...(a)freeuk.com> wrote:
> "mohangupta13" <mohangupt...(a)gmail.com> wrote in message
>
> news:2964019b-3f82-4c28-833f-d3752f3eb75f(a)h37g2000pra.googlegroups.com...
>
>
>
>
>
> > Problem: Given two strings S1 & S2 , return the common elements in
> > both the strings ??
>
> > One way I thought is to take a b-bit vector ( assuming the range of
> > elements in the strings is 0-b) ...now in the first pass through the
> > string S1 set all those bit positions that have an element equal to
> > them . i.e set i'th bit if we an element with value i..
> > Now go through S2 and and AND the i'th bit if we have an element equal
> > to i. Now return the elements for which we have a bit set.
>
> > Now there are various problems with this 1) It assumes elements in the
> > range 0-b .2) It just returns one instance of the common element .i.e
> > if S1= AABCA and S2= AAABCBA  o/p= ABC and not AAABC .
>
> > Can anyone please provide a better way to do this ( in possibly linear
> > time and as small space as possible)...??

I did meant the intersection of the multisets represented by S1 &
S2.
>
> If by better you mean, generating the right output, I used this:

By better I mean ...an algorithm that runs in linear time and uses as
little space as possible ( should ofcourse produce right output)..
>
> s1:="AABCA"
> s2:="AAABCBA"
>
> hist1:=hist2:=(0,)*256    #ie. histograms

to further reduce the number of lists used to just one I would rather
do ( suppose the length of the strings is at max n )
then i will take an x to be the smallest power of 10 such that 10^x
<n .
>
> foreach c in s1 do ++hist1[asc(c)] od

foreach c in s1 do hist1[asc(c)]+=10^x;

> foreach c in s2 do ++hist2[asc(c)] od
the seocnd loop remains same (but on hist1)

......foreach c in s2 do ++hist1[asc(c)]

now
for i:A to Z
s3+=chr(i)* ( hist1[i]/ 10^x min hist1[i]% 10^x)

>
> s3:=""
> for i:='A' to 'Z' do                # or 0 to 255
>  if hist1[i] and hist2[i] then
>   s3+ := chr(i)*(hist1[i] min hist2[i])
>  fi
> od
>
> println "S1=",s1
> println "S2=",s2
> println "S3=",s3
>
> (The if-statement is not essential, as "A"*0 is "", but is kept for
> clarity.)
>
> The process is linear I think, but requires two vectors of 256 (or perhaps
> 26, depending on your strings) elements.
>
so here i use only a single vector ......hope this works (does it ???)

Mohan

> --
> Bartc

From: bart.c on
mohangupta13 wrote:
> On 30 Apr, 14:54, "bart.c" <ba...(a)freeuk.com> wrote:
>> "mohangupta13" <mohangupt...(a)gmail.com> wrote in message
>> news:2964019b-3f82-4c28-833f-d3752f3eb75f(a)h37g2000pra.googlegroups.com...

>>> Problem: Given two strings S1 & S2 , return the common elements in
>>> both the strings ??

>>> Now there are various problems with this 1) It assumes elements in
>>> the range 0-b .2) It just returns one instance of the common
>>> element .i.e if S1= AABCA and S2= AAABCBA o/p= ABC and not AAABC .
>>
>>> Can anyone please provide a better way to do this ( in possibly
>>> linear time and as small space as possible)...??
>
> I did meant the intersection of the multisets represented by S1 &
> S2.

>> If by better you mean, generating the right output, I used this:
>
> By better I mean ...an algorithm that runs in linear time and uses as
> little space as possible ( should ofcourse produce right output)..
>>
>> s1:="AABCA"
>> s2:="AAABCBA"
>>
>> hist1:=hist2:=(0,)*256 #ie. histograms
>
> to further reduce the number of lists used to just one I would rather
> do ( suppose the length of the strings is at max n )
> then i will take an x to be the smallest power of 10 such that 10^x
> <n .
>>
>> foreach c in s1 do ++hist1[asc(c)] od
>
> foreach c in s1 do hist1[asc(c)]+=10^x;
>
>> foreach c in s2 do ++hist2[asc(c)] od
> the seocnd loop remains same (but on hist1)
>
> .....foreach c in s2 do ++hist1[asc(c)]
>
> now
> for i:A to Z
> s3+=chr(i)* ( hist1[i]/ 10^x min hist1[i]% 10^x)

In other words, you're just packing two counts into each histogram element?

I'm not sure it saves much space, as it means the count elements might have
to be twice as wide (so 32 bits instead of 16, or 64 instead of 32).

And space would only be an issue if the elements in each string could be
much larger than 8 bits: at 16-bits, the vectors needed are still small; at
32-bits, this method is no longer practical, the count vector(s) would
require several GBytes.

> so here i use only a single vector ......hope this works (does it ???)

It probably would, but I haven't tried it. (In practice, you would use a
shifted binary value, or a structure, instead of decimal shifting, but as I
said, it does't really save much. Unless perhaps in your implementation
language, arrays are in short supply)

--
Bartc

From: Ben Bacarisse on
mohangupta13 <mohangupta13(a)gmail.com> writes:

> On 30 Apr, 14:54, "bart.c" <ba...(a)freeuk.com> wrote:
>> "mohangupta13" <mohangupt...(a)gmail.com> wrote in message
>> news:2964019b-3f82-4c28-833f-d3752f3eb75f(a)h37g2000pra.googlegroups.com...
>>
>> > Problem: Given two strings S1 & S2 , return the common elements in
>> > both the strings ??
>>
>> > One way I thought is to take a b-bit vector ( assuming the range of
>> > elements in the strings is 0-b) ...now in the first pass through the
>> > string S1 set all those bit positions that have an element equal to
>> > them . i.e set i'th bit if we an element with value i..
>> > Now go through S2 and and AND the i'th bit if we have an element equal
>> > to i. Now return the elements for which we have a bit set.
>>
>> > Now there are various problems with this 1) It assumes elements in the
>> > range 0-b .2) It just returns one instance of the common element .i.e
>> > if S1= AABCA and S2= AAABCBA  o/p= ABC and not AAABC .
>>
>> > Can anyone please provide a better way to do this ( in possibly linear
>> > time and as small space as possible)...??
>
> I did meant the intersection of the multisets represented by S1 &
> S2.
<snip>
> so here i use only a single vector ......hope this works (does it ???)

You need only one vector of counts if you count up as you scan one string
and count down as you scan the second:

void intersect(char *result, const unsigned char *s1, const unsigned char *s2)
{
size_t count[UCHAR_MAX] = {0};
while (*s1)
++count[*s1++];
for (; *s2; ++s2)
if (count[*s2]) {
--count[*s2]
*result++ = *s2;
}
}

Of course, you don't get the result in sorted order but that was not
part of the original specification. (size_t is an unsigned type BTW).

--
Ben.
From: mohangupta13 on
On Apr 30, 7:16 pm, Ben Bacarisse <ben.use...(a)bsb.me.uk> wrote:
> mohangupta13 <mohangupt...(a)gmail.com> writes:
> > On 30 Apr, 14:54, "bart.c" <ba...(a)freeuk.com> wrote:
> >> "mohangupta13" <mohangupt...(a)gmail.com> wrote in message
> >>news:2964019b-3f82-4c28-833f-d3752f3eb75f(a)h37g2000pra.googlegroups.com....
>
> >> > Problem: Given two strings S1 & S2 , return the common elements in
> >> > both the strings ??
>
> >> > One way I thought is to take a b-bit vector ( assuming the range of
> >> > elements in the strings is 0-b) ...now in the first pass through the
> >> > string S1 set all those bit positions that have an element equal to
> >> > them . i.e set i'th bit if we an element with value i..
> >> > Now go through S2 and and AND the i'th bit if we have an element equal
> >> > to i. Now return the elements for which we have a bit set.
>
> >> > Now there are various problems with this 1) It assumes elements in the
> >> > range 0-b .2) It just returns one instance of the common element .i.e
> >> > if S1= AABCA and S2= AAABCBA  o/p= ABC and not AAABC .
>
> >> > Can anyone please provide a better way to do this ( in possibly linear
> >> > time and as small space as possible)...??
>
> >  I did meant the intersection of the multisets represented by S1 &
> > S2.
> <snip>
> > so here i use only a single vector ......hope this works (does it ???)
>
> You need only one vector of counts if you count up as you scan one string
> and count down as you scan the second:
Oh I am so stupid ..i did think about this up and down scan but
didn't got that working ..

>
> void intersect(char *result, const unsigned char *s1, const unsigned char *s2)
> {
>      size_t count[UCHAR_MAX] = {0};
>      while (*s1)
>           ++count[*s1++];
>      for (; *s2; ++s2)
>           if (count[*s2]) {
>                --count[*s2]
>                *result++ = *s2;
>           }
>
> }
>
> Of course, you don't get the result in sorted order but that was not
> part of the original specification.  (size_t is an unsigned type BTW).

Thanks Ben,

>
> --
> Ben.

This might be the fourth time I am asking it here (havn't got
satisfactory answers yet).

How can one prove (either mathematically or just by intuition ) that
the run time of an algorithm or the memory use of it is the best we
can do for the particular problem ??? ( I mean how can one say that a
particular algorithm is the best for the given problem )???

I know its not always possible to say such things "for some
problems"..but for major class of problems its know what is the best
possible like for a comparison sort the lower bound is well know (nlg
n).

Any reference to some resource will also do ... ( some one previously
referred me to " MIT lectures on Structure and Interpretation of
computer programs" ..i did that but still the doubt persists.)
Thanks
Mohan.