Given a matrix containing lower alphabetical characters only, we need to count number of palindromic paths in given matrix. A path is defined as a sequence of cells starting from top-left cell and ending at bottom-right cell. We are allowed to move to right and down only from current cell.
Examples:
Input : mat[][] = {"aaab”, 
                   "baaa”
                   “abba”}
Output : 3
Number of palindromic paths are 3 from top-left to 
bottom-right.
aaaaaa (0, 0) -> (0, 1) -> (1, 1) -> (1, 2) -> 
                                (1, 3) -> (2, 3)    
aaaaaa (0, 0) -> (0, 1) -> (0, 2) -> (1, 2) -> 
                                (1, 3) -> (2, 3)    
abaaba (0, 0) -> (1, 0) -> (1, 1) -> (1, 2) -> 
                                 (2, 2) -> (2, 3)    
We can solve this problem recursively, we start from two corners of a palindromic path(top-left and bottom right). In each recursive call, we maintain a state which will constitute two cells one from starting and one from end which should be equal for palindrome property. If at a state, both cell characters are equal then we call recursively with all possible movements in both directions.
As this can lead to solving same subproblem multiple times, we have taken a map memo in below code which stores the calculated result with key as indices of starting and ending cell so if subproblem with same starting and ending cell is called again, result will be returned by memo directly instead of recalculating again.
Implementation:
CPP
| // C++ program to get number of palindrome// paths in matrix#include <bits/stdc++.h>usingnamespacestd;#define R 3#define C 4// struct to represent state of recursion// and key of mapstructcells{    //  indices of front cell    intrs, cs;    //  indices of end cell    intre, ce;    cells(intrs, intcs, intre, intce)        : rs(rs)        , cs(cs)        , re(re)        , ce(ce)    {    }    // operator overloading to compare two    // cells which rs needed for map    booloperator<(constcells& other) const    {        return((rs != other.rs) || (cs != other.cs)                || (re != other.re) || (ce != other.ce));    }};// recursive method to return number//  of palindromic paths in matrix// (rs, cs) ==> Indices of current cell //              from a starting point (First Row)// (re, ce) ==> Indices of current cell //              from a ending point (Last Row)// memo     ==> To store results of //              already computed problemsintgetPalindromicPathsRecur(charmat[R][C],                              intrs, intcs,                             intre, intce,                             map<cells, int>& memo){    // Base Case 1 : if any index rs out of boundary,    // return 0    if(rs < 0 || rs >= R || cs < 0 || cs >= C)        return0;    if(re < 0 || re < rs || ce < 0 || ce < cs)        return0;    // Base case 2 : if values are not equal    // then palindrome property rs not satisfied,    // so return 0    if(mat[rs][cs] != mat[re][ce])        return0;    // If we reach here, then matrix cells are same.    // Base Case 3 : if indices are adjacent then    // return 1    if(abs((rs - re) + (cs - ce)) <= 1)        return1;    //  if result rs precalculated, return from map    if(memo.find(cells(rs, cs, re, ce))         != memo.end())        returnmemo[cells(rs, cs, re, ce)];    intret = 0; // Initialize result    // calling recursively for all possible movements    ret += getPalindromicPathsRecur(mat, rs + 1,                                     cs, re - 1,                                    ce, memo);    ret += getPalindromicPathsRecur(mat, rs + 1,                                     cs, re,                                    ce - 1, memo);    ret += getPalindromicPathsRecur(mat, rs,                                     cs + 1, re - 1,                                    ce, memo);    ret += getPalindromicPathsRecur(mat, rs,                                     cs + 1, re,                                    ce - 1, memo);    // storing the calculated result in map    memo[cells(rs, cs, re, ce)] = ret;    returnret;}//  method returns number of palindromic paths in matrixintgetPalindromicPaths(charmat[R][C]){    map<cells, int> memo;    returngetPalindromicPathsRecur(mat, 0, 0, R - 1, C - 1,                                    memo);}//  Driver code intmain(){    charmat[R][C] = { 'a', 'a', 'a',                       'b', 'b', 'a',                       'a', 'a', 'a',                      'b', 'b', 'a'};    printf("%d", getPalindromicPaths(mat));    return0;} | 
Java
| // Java program to get number of palindrome paths in matriximportjava.util.HashMap;// Cells class definitionclassCells {  intrs;  intcs;  intre;  intce;  // Constructor  publicCells(intrs, intcs, intre, intce)  {    this.rs = rs;    this.cs = cs;    this.re = re;    this.ce = ce;  }  // Equals method to compare two Cells objects  @Overridepublicbooleanequals(Object o)  {    if(o instanceofCells) {      Cells other = (Cells)o;      return(rs == other.rs) && (cs == other.cs)        && (re == other.re) && (ce == other.ce);    }    returnfalse;  }  // hashCode() function to calculate hash  @OverridepublicinthashCode()  {    return(rs * 100+ cs) * 100+ (re * 100+ ce);  }}classPalindromicPaths {  // Rows and Columns in the matrix  staticintR = 3;  staticintC = 4;  //  method to return number of palindromic paths in  //  matrix  staticintgetPalindromicPaths(char[][] mat)  {    HashMap<Cells, Integer> memo = newHashMap<>();    R = mat.length;    C = mat[0].length;    returngetPalindromicPathsRecur(mat, 0, 0, R - 1,                                    C - 1, memo);  }  // recursive method to return number of palindromic  // paths in matrix  staticint    getPalindromicPathsRecur(char[][] mat, intrs, intcs,                             intre, intce,                             HashMap<Cells, Integer> memo)  {    // Base Case 1 : if any index is out of boundary,    // return 0    if(rs < 0|| rs >= R || cs < 0|| cs >= C) {      return0;    }    if(re < 0|| re < rs || ce < 0|| ce < cs) {      return0;    }    // Base case 2 : if values are not equal then    // palindrome property is not satisfied, so return 0    if(mat[rs][cs] != mat[re][ce]) {      return0;    }    // If we reach here, then matrix cells are same.    // Base Case 3 : if indices are adjacent then return    // 1    if(Math.abs((rs - re) + (cs - ce)) <= 1) {      return1;    }    Cells key = newCells(rs, cs, re, ce);    //  if result is precalculated, return from map    if(memo.containsKey(key)) {      returnmemo.get(key);    }    intret = 0; // Initialize result    // calling recursively for all possible movements    ret += getPalindromicPathsRecur(mat, rs + 1, cs,                                    re - 1, ce, memo);    ret += getPalindromicPathsRecur(mat, rs + 1, cs, re,                                    ce - 1, memo);    ret += getPalindromicPathsRecur(mat, rs, cs + 1,                                    re - 1, ce, memo);    ret += getPalindromicPathsRecur(      mat, rs, cs + 1, re - 1, ce - 1, memo);    // storing the calculated result in map    memo.put(key, ret);    returnret;  }  // Driver code  publicstaticvoidmain(String[] args)  {    char[][] mat = { { 'a', 'a', 'a'},                    { 'b', 'b', 'a'},                    { 'a', 'a', 'a'},                    { 'b', 'b', 'a'} };    System.out.println(getPalindromicPaths(mat));  }}// This code is contributed by phasing17. | 
Python3
| # Python3 program to get number of palindrome# paths in matrixR =3C =4# struct to represent state of recursion# and key of mapclassCells:    def__init__(self, rs, cs, re, ce):        self.rs =rs        self.cs =cs        self.re =re        self.ce =ce    def__eq__(self, other):        ifother:            return(self.rs, self.cs, self.re, self.ce) ==(other.rs, other.cs, other.re, other.ce)        returnFalse            def__hash__(self):        returnhash((self.rs, self.cs, self.re, self.ce))# recursive method to return number#  of palindromic paths in matrix# (rs, cs) ==> Indices of current cell #              from a starting point (First Row)# (re, ce) ==> Indices of current cell #              from a ending point (Last Row)# memo     ==> To store results of #              already computed problemsdefgetPalindromicPathsRecur(mat, rs, cs, re, ce, memo):        # Base Case 1 : if any index rs out of boundary,    # return 0    ifrs < 0orrs >=R orcs < 0orcs >=C:        return0    ifre < 0orre < rs orce < 0orce < cs:        return0    # Base case 2 : if values are not equal    # then palindrome property rs not satisfied,    # so return 0    ifmat[rs][cs] !=mat[re][ce]:        return0    # If we reach here, then matrix cells are same.    # Base Case 3 : if indices are adjacent then    # return 1    ifabs((rs -re) +(cs -ce)) <=1:        return1    key =Cells(rs, cs, re, ce)    #  if result rs precalculated, return from map    ifkey inmemo:        returnmemo[key]    ret =0# Initialize result    # calling recursively for all possible movements    ret +=getPalindromicPathsRecur(mat, rs +1, cs, re -1, ce, memo)    ret +=getPalindromicPathsRecur(mat, rs +1, cs, re, ce -1, memo)    ret +=getPalindromicPathsRecur(mat, rs, cs +1, re -1, ce, memo)    ret +=getPalindromicPathsRecur(mat, rs, cs +1, re -1, ce -1, memo)    # storing the calculated result in map    memo[key] =ret    returnret#  method returns number of palindromic paths in matrixdefgetPalindromicPaths(mat):    memo ={}    R =len(mat)    C =len(mat[0])    res =getPalindromicPathsRecur(mat, 0, 0, R -1, C -1, memo)    returnres#  Driver code if__name__ =="__main__":    mat =[['a', 'a', 'a'],            ['b', 'b', 'a'],            ['a', 'a', 'a'],            ['b', 'b', 'a']]    print(getPalindromicPaths(mat))    # This code is contributed by phasing17. | 
C#
| // C# program to get number of palindrome paths in matrixusingSystem;usingSystem.Collections.Generic;// Cells class definitionclassCells {  intrs;  intcs;  intre;  intce;  // Constructor  publicCells(intrs, intcs, intre, intce)  {    this.rs = rs;    this.cs = cs;    this.re = re;    this.ce = ce;  }  // Equals method to compare two Cells objects  publicoverrideboolEquals(Object o)  {    if(o isCells) {      Cells other = (Cells)o;      return(rs == other.rs) && (cs == other.cs)        && (re == other.re) && (ce == other.ce);    }    returnfalse;  }  // hashCode() function to calculate hash  publicoverrideintGetHashCode()  {    return(rs * 100 + cs) * 100 + (re * 100 + ce);  }}classPalindromicPaths {  // Rows and Columns in the matrix  staticintR = 3;  staticintC = 4;  //  method to return number of palindromic paths in  //  matrix  staticintGetPalindromicPaths(char[][] mat)  {    Dictionary<Cells, int> memo      = newDictionary<Cells, int>();    R = mat.Length;    C = mat[0].Length;    returnGetPalindromicPathsRecur(mat, 0, 0, R - 1,                                    C - 1, memo);  }  // recursive method to return number of palindromic  // paths in matrix  staticint    GetPalindromicPathsRecur(char[][] mat, intrs, intcs,                             intre, intce,                             Dictionary<Cells, int> memo)  {    // Base Case 1 : if any index is out of boundary,    // return 0    if(rs < 0 || rs >= R || cs < 0 || cs >= C) {      return0;    }    if(re < 0 || re < rs || ce < 0 || ce < cs) {      return0;    }    // Base case 2 : if values are not equal then    // palindrome property is not satisfied, so return 0    if(mat[rs][cs] != mat[re][ce]) {      return0;    }    // If we reach here, then matrix cells are same.    // Base Case 3 : if indices are adjacent then return    // 1    if(Math.Abs((rs - re) + (cs - ce)) <= 1) {      return1;    }    Cells key = newCells(rs, cs, re, ce);    //  if result is precalculated, return from map    if(memo.ContainsKey(key)) {      returnmemo[key];    }    intret = 0; // Initialize result    // calling recursively for all possible movements    ret += GetPalindromicPathsRecur(mat, rs + 1, cs,                                    re - 1, ce, memo);    ret += GetPalindromicPathsRecur(mat, rs + 1, cs, re,                                    ce - 1, memo);    ret += GetPalindromicPathsRecur(mat, rs, cs + 1,                                    re - 1, ce, memo);    ret += GetPalindromicPathsRecur(      mat, rs, cs + 1, re - 1, ce - 1, memo);    // storing the calculated result in map    memo[key] = ret;    returnret;  }  // Driver code  publicstaticvoidMain(string[] args)  {    char[][] mat = { newchar[] { 'a', 'a', 'a'},                    newchar[] { 'b', 'b', 'a'},                    newchar[] { 'a', 'a', 'a'},                    newchar[] { 'b', 'b', 'a'} };    Console.WriteLine(GetPalindromicPaths(mat));  }}// This code is contributed by phasing17. | 
Javascript
| // JavaScript code to get number of palindrome paths in matrixconst R = 3;const C = 4;// class to represent state of recursion// and key of mapclass Cells {  constructor(rs, cs, re, ce) {    this.rs = rs;    this.cs = cs;    this.re = re;    this.ce = ce;  }  // custom equality check  equals(other) {    if(other) {      return(        this.rs === other.rs &&        this.cs === other.cs &&        this.re === other.re &&        this.ce === other.ce      );    }    returnfalse;  }}// map to store results of already computed problemsconst memo = newMap();// recursive method to return number of palindromic paths in matrix// (rs, cs) ==> Indices of current cell from a starting point (First Row)// (re, ce) ==> Indices of current cell from a ending point (Last Row)functiongetPalindromicPathsRecur(mat, rs, cs, re, ce) {  // Base Case 1 : if any index rs out of boundary, return 0  if(rs < 0 || rs >= R || cs < 0 || cs >= C) {    return0;  }  if(re < 0 || re < rs || ce < 0 || ce < cs) {    return0;  }  // Base case 2 : if values are not equal then palindrome property rs not satisfied, so return 0  if(mat[rs][cs] !== mat[re][ce]) {    return0;  }  // If we reach here, then matrix cells are same.  // Base Case 3 : if indices are adjacent then return 1  if(Math.abs((rs - re) + (cs - ce)) <= 1) {    return1;  }  const key = newCells(rs, cs, re, ce);  //  if result rs precalculated, return from map  if(memo.has(key)) {    returnmemo.get(key);  }  let ret = 0; // Initialize result  // calling recursively for all possible movements  ret += getPalindromicPathsRecur(mat, rs + 1, cs, re - 1, ce);  ret += getPalindromicPathsRecur(mat, rs + 1, cs, re, ce - 1);  ret += getPalindromicPathsRecur(mat, rs, cs + 1, re - 1, ce);  ret += getPalindromicPathsRecur(mat, rs, cs + 1, re - 1, ce - 1);  // storing the calculated result in map  memo.set(key, ret);  returnret;}//  method returns number of palindromic paths in matrixfunctiongetPalindromicPaths(mat) {  const R = mat.length;  const C = mat[0].length;  const res = getPalindromicPathsRecur(mat, 0, 0, R - 1, C - 1);  returnres;}//  Driver codelet mat = [['a', 'a', 'a'],            ['b', 'b', 'a'],            ['a', 'a', 'a'],            ['b', 'b', 'a']]console.log(getPalindromicPaths(mat))// This code is contributed by phasing17. | 
3
Time Complexity : O((R x C)2)
Space Complexity : O((R x C)2) due to use of memoization map.
This article is contributed by Utkarsh Trivedi. If you like neveropen and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the neveropen main page and help other Geeks.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!


 
                                    








