3

I am trying to solve a problem where I am given a nXn square matrix of characters and I want to find out size of the largest palindrome square from this? The largest palindrome square is, a square with all rows and all columns as palindrome.

For eg. Input

a g h j k
s d g d j
s e f e n
a d g d h 
r y d g s

The output will be:

3

corresponding to the middle square. I am thinking of dynamic programming solution but unable to formulate the recurrence relation. I am thinking the dimensions should be a(i,j,k) where i, j are the bottom-right of rectangle and k be the size of palindrome square. Can someone help me with the recurrence relation for this problem?

EDIT:

n<500, so I believe that I can't go beyond O(n^3).

Naman
  • 2,569
  • 4
  • 27
  • 44
  • you will probably also want a couple variables to record which column or row you are testing for a valid palindrome – Calum Mar 15 '15 at 22:37
  • Exactly, that's what I am stuck at, I want to do it in time complexity of O(n^3). I am still not able to get the recurrence relation. – Naman Mar 15 '15 at 22:45

3 Answers3

3

Assuming that you can solve the following problem:

  • Ending at cell (i, j) is there any palindrome with different length horizontally and vertically.

Hint for above problem:

   boolean[][][]palindrome;//Is there any palindrome ending at (i , j) has length k
   for(int i = 0; i < n; i++){
       for(int j = 0; j < n; j++){
           palindrome[i][j][0] = true;
           palindrome[i][j][1] = true;
           for(int k = 2; k <= n; k++)
               if(data[i][j - k + 1] == data[i][j] && palindrome[i][j - 1][k - 2])
                  palindrome[i][j][k] = true; 
       } 
  }         

So, we can create two three dimensional arrays int[n][n][n]col and int[n][n][n]row.

For each cell(i, j), we will calculate the total number of palindrome with length k, ending at cell (0, j), (1, j) , ... (i, j) and total number of palindrome with length k, ending at cell (i,0), (i, 1), ... (i, j)

for(int k = 1; k <= n; k++)
    if(there is palindrome length k horizontally, end at cell (i, j)) 
       row[i][j][k] = 1 + row[i - 1][j][k];
    if(there is palindrome length k vertically, end at cell (i, j)) 
       col[i][j][k] = 1 + col[i][j - 1][k]; 

Finally, if row[i][j][k] >= k && col[i][j][k] >= k -> there is an square palindrome length k ending at (i,j).

In total, the time complexity will be O(n^3)

Pham Trung
  • 11,204
  • 2
  • 24
  • 43
  • Really good solution. It worked. I curse myself every time, I am not able to solve a DP problem. – Naman Mar 17 '15 at 03:49
  • @Naman glad it help, you may just need some practice, don't worry :) – Pham Trung Mar 17 '15 at 03:50
  • Thanks again. If you don't mind, can you please have a look at this problem also? http://stackoverflow.com/questions/24863373/what-can-be-space-efficient-algorithm-for-single-row-of-skyscraper-puzzle I could find the solution, but it is O(n^3). I just wanna know if it is possible in O(n^2)? Don't worry about the space complexity according to the problem description. I had asked that quite a long time ago. – Naman Mar 17 '15 at 04:04
  • @Naman you want to have a O(n^2) time complexity for above problem? – Pham Trung Mar 17 '15 at 04:40
  • No, not for this problem. I have accepted this answer. I am asking for some other problem, it's the skypscrapper problem given in the link? http://stackoverflow.com/questions/24863373/what-can-be-space-efficient-algorithm-for-single-row-of-skyscraper-puzzle – Naman Mar 17 '15 at 04:43
  • @PhamTrung can you please suggest how can I can reduce memory ? – Brajesh Kumar Oct 01 '15 at 11:03
0

lets start with the complexity of validating a palindrome:

A palindrome can be identified in O(k) where k is the length of the palindrome see here

you then want need to do that test 2k times once for each row and column in you r inner square. (using the length of the palindrome k, as the dimension)

so now you have k * 2k -> O(2k^2) -> O(k^2)

then you want to increase the possible search space to the whole data set nxn this is when a 2nd variable gets introduced

you will need to iterate over columns 1 to (n-k) and all rows 1 to (n-k) in a nested loop.

so now you have (n-k)^2 * O(k^2) -> O(n^2 * k^2)

Note: this problem is dependant on more than one variable

This is the same approach i suggest you take to coding the solution, start small and get bigger

Community
  • 1
  • 1
Calum
  • 2,110
  • 2
  • 22
  • 39
  • That's the naive brute force approach, I am aware of that but I wanted to know if this can be done with dynamic programming in better than O(n^2 * k^2) (which is O(n^4) in worst case). I am sorry, I should edit the problem that I am not looking for the brute force approach. – Naman Mar 16 '15 at 01:03
  • fair enough, in that case you could consider checking every k'th row and column. then you only need test the rows columns between those when the edge rows / columns pass. Possibly storing the palindrome tests results in a 2D array – Calum Mar 16 '15 at 01:33
  • @Calcum Sorry I am unable to get you, can you please edit your answer with this new algorithm that you are suggesting? – Naman Mar 16 '15 at 01:51
0

Im sure there is probably a better way, and im pretty sure my logic is correct so take this at face value as its not tested.

Just to make the example easy im going to say that i,j is the top left corner or coordinates 1,1

  1 2 3 4 5 6 7 8
1 a b c d e f g f 
2 d e f g h j k q 
3 a b g d z f g f 
4 a a a a a a a a

ie (1,1) = a, (1,5) = e and (2,1) = d

now instead of checking every column you could start by checking every kth column

ie when k=3

1) create a 2D boolean array the size of the character table all results TRUE

2) I start by checking column 3 cfg which is not a palindrome, thus I no longer need to test columns 1 or 2.

3) because the palindrome test failed marked the coresponding result in the 2D array (1,3) as FALSE (I know not to test any range that uses this position as it is not a palindrome)

4) Next check column 6, fjf which is a palindrome so I go back and test column 5, ehz != a palindrome

5) set (1,5) = FALSE

6) Then test column 8 then 7,

NOTE: You have only had to test 5 of the 8 columns.

since there were k columns in a row that were palindromes, now test the corresponding rows. Start from the bottom row in this case 3 as it will eliminate the most other checks if it fails

7) check row starting at (3,6) fgf = palindrome

8) check row starting at (2,6) jkq != a palindrome

9) set (2,6) = FALSE

10) check column starting at (2,3) daa != palindrome

11) set (2,3) = FALSE

Dont need to test any more for row 2 as both (2,3) and (2,6) are FALSE

Hopefully you can make sense of that.

Note: you would probably start this at k = n and decrement k until you find a result

Calum
  • 2,110
  • 2
  • 22
  • 39
  • I truly appreciate you for the help but I really cant make complete sense of all this. Because, 1) I need to find the largest such 'k', I am not given one. 2) I still feel your code is O(n^4) in worst case. I really can't take this at face value. I really don't believe that it's implementation can even reach till the value of n=200. In my case, I have to handle n<500 – Naman Mar 16 '15 at 04:12