One Point Solution

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Sunday, 11 March 2012

Codeforces: VK Cup round 1: Problem C: Abracadabra

Posted on 19:57 by Unknown
This problem haunted me all day and I kept solving it inside my head without really wanting to. At the end, the solution I thought of all day was sort of incomplete, but a little dirty trick can make it pass. Later I saw some other codes and finally noticed the hard reality...

The divide and conquer
First of all, let us say that we care about the string present after a number of steps equal to step (30 for the string we want to solve). We can tell the size of the string (t = 2^step - 1). We can know the position of them middle character m = t/2 + 1. Please note that due to how the string is constructed, the middle character is unique - this character does not appear in any other position of the string at this number of steps.

In fact, that's really all we need to know how to use divide and conquer in this problem. Let us say that the result greatest common substring contains this middle character, then it is forcefully the overlap between the two intervals. If the best substring is not the overlap between the two intervals, then it won't contain the middle character.

In fact, we can split each of the intervals into two maximal parts (possibly empty) that do not contain the middle character. And each of these four parts will match an interval in the string for step # (step - 1). (The positions of the intervals that appear after the middle, shall get the middle position subtracted).

The result is thus one of five possibilities: It can be the overlap of the two intervals. Or it can be the largest substring (same sub-problem) between one of the four possible pairs between strings that come from the first interval and strings that come from the second.

This solution as is has a lot of branching. Worst case may call the divide and conquer recurrence 4^30 times.

Dirty tricks
First of all, we will handle trivial cases such as when one of the intervals is empty. The result is obviously always 0 in those cases.

But there are ways to optimize that original 4^30 idea. What I did was to make sure that it is 2^30, avoiding to branch the recurrence more than two times per instance, this requires some tricks like not doing the split when both intervals begin at the first position or end at the last (It can be proven the overlap is the best result in this case). Even at 2^30, it is too slow, the second dirty trick was to do an array mem[80][80][80][80], and if both extremes are less than 80, memoize the results of the recurrence. This will make the number of calls from 2^30 to 2^30 / (80^4) + 80^4. This is enough to solve the problem.

The better solution
A smarter solution involves noticing, what if one interval is completely inside the other? In this case, the overlap is 100% surely the best answer (And it is actually equal to the size of the smallest string). It is easy to know that this will give a correct answer. It is slightly more complicated to notice that this little optimization will make the algorithm run very fast. In fact, the maximum number of branches is 2, so the result is O(step). Really.

As a slight proof, let us think of a pair of intervals such that one is not a subset of the other.

1) If neither interval touches the middle letter, the only pair that is not trivial (does not have an empty string) will be one that matches the two intervals again but in the previous step. No branching.
2) If both intervals touch the middle letter, there will be branching. Yes. But 2 of the pairs of intervals generated will be cases in which one interval is a subset of the other. So the case will branch 2 times, and both times the case will an interval that begins at position 1 with another interval that ends at position t.
3) Handling Case 2 will either result in a sub-problem in which one interval is a subset or the other, or in Case 2 again. Try it.

int solve(int l1, int r1, int l2, int r2, int step=30) 
{
if (l1 > r1) {
return 0;
}
if (l2 > r2) {
return 0;
}
//overlap
int ovl = max(l1, l2);
int ovr = min(r1, r2);
int overlap = ( (ovr >= ovl)? (ovr - ovl + 1) : 0 );

int t = (1<<step) - 1;

int m = t/2 + 1; //the middle

// should we continue in depth? (Is the result not necessarily the overlap?)
if ( (l1 <= l2 && r1 >= r2) || (l2 <= l1 && r2 >= r1)) { //one is a subset of the other
return overlap;
}
// split each interval in two halves that don't touch the middle.
int l[4] = { min(l1, m) , max(m+1, l1) - m, min(l2, m) , max(m+1, l2) - m};
int r[4] = { min(r1, m-1), max(m, r1) - m, min(r2, m-1), max(m, r2) - m};
int res = overlap;
// try each pair of interval.
for (int i=0; i<2; i++) {
for (int j=2; j<4; j++) {
res = max(res, solve(l[i],r[i], l[j], r[j], step-1) );
}
}
return res;

}
Email ThisBlogThis!Share to XShare to Facebook
Posted in codeforces, vkcup | No comments
Newer Post Older Post Home

0 comments:

Post a Comment

Subscribe to: Post Comments (Atom)

Popular Posts

  • TopCoder SRM 557 - finally
    SRM 557 Explanation for division 1 Easy and match recap. Explanations for div2 easy and div2 medium. It feels like it has been ages since t...
  • SRM 589 Editorial
    I have finished writing the editorial for TopCoder SRM 589: http://apps.topcoder.com/wiki/display/tc/SRM+589 . As you most likely noticed. L...
  • SRM 590 recap and editorial
    Another week another Topcoder match. Not a great day. I had a bad flu and still do. Div1 500: The one with Xor Given a list of cards with nu...
  • SRM 546: relief
    I figured I should post something about this SRM. I've been very busy these weeks because the semester is ending and I tried to win a t-...
  • SRM 526: The killing wait for results
    While I wait for results, here is my perspective on this algorithm contest. It began with issues, it had to be postponed 15 minutes. TC has ...
  • SRM 554 div1 hard: TheBrickTowerHardDivOne
    Link to problem statement We got infinitely many bricks of dimensions 1x1x1 and C different colors. Count the number of towers of size 2x2...
  • SRM 533: Div1 500 MagicBoard explanation
    Finally solved it. It is a nice problem that is worth explaining in a post. You have a grid/board of at most 50x50 cells. Some cells contain...
  • Member SRM 505: Part 1
    So, let me explain a couple of problems from a Topcoder Member SRM that I wrote and never got an editorial. BTW, it was the last member SRM....
  • ListedLinks 2012-02-10
    Saturday Morning Breakfast Cereal comics: Grace Hopper's ghost That Oracle engineer blog post Oracle would really not like anyone to se...
  • Codeforces "Good bye 2013" round
    So it was a special round for coders of both divisions, problems ranged from the super easy problem A to the super difficult problems E,F,G....

Categories

  • acm
  • algorithm
  • answers
  • arenaplugin
  • badday
  • behindthescenes
  • bugs
  • c++
  • censorship
  • codechef
  • codeforces
  • contests
  • crocchamp
  • editorial
  • editorial.srm
  • embarrassing
  • explanation
  • gcj2013
  • gmp
  • goodday
  • google
  • googlecodejam
  • greed
  • groklaw
  • health
  • html
  • httpseverywhere
  • implementation
  • ipsc
  • ispc
  • java
  • kawigiedit
  • kindagoodday
  • lamebook
  • languages
  • lego
  • listedlinks
  • marathon
  • nasa
  • offtopic
  • ouch
  • postmortem
  • postportem
  • practical
  • probably_not_a_good_tip
  • problemsetting
  • programming
  • python
  • quora
  • rant
  • recap
  • slightlygoodday
  • snippet
  • srm
  • stl
  • strategy
  • swerc
  • tco
  • tco12
  • tco13
  • tco2012
  • tco2013
  • ternarysearch
  • topcoder
  • tricks
  • ubuntu
  • uva
  • vjass
  • vkcup
  • wc3
  • zinc

Blog Archive

  • ►  2014 (1)
    • ►  January (1)
  • ►  2013 (141)
    • ►  December (14)
    • ►  November (8)
    • ►  October (13)
    • ►  September (11)
    • ►  August (14)
    • ►  July (15)
    • ►  June (13)
    • ►  May (13)
    • ►  April (12)
    • ►  March (11)
    • ►  February (11)
    • ►  January (6)
  • ▼  2012 (94)
    • ►  December (5)
    • ►  October (6)
    • ►  September (8)
    • ►  August (6)
    • ►  July (3)
    • ►  June (5)
    • ►  May (8)
    • ►  April (10)
    • ▼  March (20)
      • Topcoder Open 2012 round 1A
      • Codeforces round #114. 167C: Wizards and numbers
      • Official TCO 2012 blogger
      • Codeforces round #114 (div1)
      • 5 reasons editorial votes in Topcoder are useless
      • Codeforces VK Cup round 2: (ouch)
      • Codeforces round #113 div2 (unofficial)
      • Writing SRM 538
      • SRM 537: oh my
      • Codeforces round #112
      • Language features: Rants and wishes
      • Google code jam registration - Just note something...
      • Codeforces: VK Cup round 1: Problem C: Abracadabra
      • Codeforces: VK Cup round 1 (update 1)
      • SRM 536: heh
      • SRM 535 editorial: The making of
      • Codeforces round #111 (div2 only)
      • SRM 535 : lame
      • A note about SRM 537 and 540 money prizes
      • The March of Destruction begins!
    • ►  February (16)
    • ►  January (7)
  • ►  2011 (51)
    • ►  December (7)
    • ►  November (12)
    • ►  October (5)
    • ►  September (1)
    • ►  August (3)
    • ►  July (4)
    • ►  June (3)
    • ►  May (7)
    • ►  April (3)
    • ►  March (2)
    • ►  February (1)
    • ►  January (3)
  • ►  2010 (9)
    • ►  December (4)
    • ►  October (1)
    • ►  June (1)
    • ►  May (1)
    • ►  January (2)
  • ►  2009 (1)
    • ►  December (1)
Powered by Blogger.

About Me

Unknown
View my complete profile