Maximize A[i]*B[i] + A[i]*B[j] + A[j]*B[j], i != j, given two unordered lists of positive integers - arrays

Can you help me with the algorithm:
Given 2 arrays of equal size a[] and b[] with integer numbers greater or equal to 1.
Find non-equal indices i and j (i != j) such that the value -
max(a[i]*b[i] + a[i] * b[j] + a[j] * b[j], a[i]*b[i] + a[j] * b[i] + a[j] * b[j])
will be maximum.
Example:
a = [1, 9, 6, 6] and b = [9, 1, 6, 6].
Maximum will be at i = 2 and j = 3 (zero-based indexing):
a[2]*b[2] + a[2]*b[3] + a[3] * b[3] = 6*6+6*6+6*6 = 108
Is there a way to find i and j in less then quadratic time?
And the same question for finding objective function value in less then quadratic time?
Thank you!

Here's my attempt at implementing David Eisenstat's idea. I think the i != j restriction made this more complicated but either way, I'd welcome suggestions on improving the code. There's a test at the end against brute force.
The construction of the upper envelope for the lines A[i]*x + A[i]*B[i] relies on Andrew's monotone chain convex hull algorithm applied to the dual points transformed from the lines.
Python code:
# Upper envelope of lines in the plane
from fractions import Fraction
import collections
def get_dual_point(line):
return (line[0], -line[1])
def get_primal_point(dual_line):
return (dual_line[0], -dual_line[1])
def get_line_from_two_points(p1, p2):
if p1[0] == p2[0]:
return (float('inf'), 0)
m = Fraction(p1[1] - p2[1], p1[0] - p2[0])
b = -m * p1[0] + p1[1]
return (m, b)
def cross_product(o, a, b):
return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
# lower_hull has the structure [(dual_point, original_line, leftmost_x, index)]
def get_segment_idx(lower_hull, x):
lo = 0
hi = len(lower_hull) - 1
# Find the index of the first
# x coordinate greater than x
while lo < hi:
mid = lo + (hi - lo + 1) // 2
if lower_hull[mid][2] <= x:
lo = mid
else:
hi = mid - 1
return lo
# Assumes we add points in order of increasing x-coordinates
def add_right_to_lower_hull(lower_hull, point):
while len(lower_hull) > 0 and lower_hull[-1][0][0] == point[0][0] and lower_hull[-1][0][1] > point[0][1]:
lower_hull.pop()
while len(lower_hull) > 1 and cross_product(lower_hull[-2][0], lower_hull[-1][0], point[0]) <= 0:
lower_hull.pop()
if not lower_hull or lower_hull[-1][0][0] != point[0][0]:
lower_hull.append(point)
# Each segment of the lower hull
# in the dual plane is a line intersection
# in the primal plane.
if len(lower_hull) == 1:
lower_hull[0][2] = -float('inf')
else:
line = get_line_from_two_points(lower_hull[-1][0], lower_hull[-2][0])
lower_hull[-1][2] = get_primal_point(line)[0]
return lower_hull
# Assumes we add points in order of decreasing x-coordinates
def add_left_to_lower_hull(lower_hull, point):
while len(lower_hull) > 0 and lower_hull[0][0][0] == point[0][0] and lower_hull[0][0][1] > point[0][1]:
lower_hull.popleft()
while len(lower_hull) > 1 and cross_product(lower_hull[1][0], lower_hull[0][0], point[0]) >= 0:
lower_hull.popleft()
if not lower_hull or lower_hull[0][0][0] != point[0][0]:
lower_hull.appendleft(point)
# Each segment of the lower hull
# in the dual plane is a line intersection
# in the primal plane.
if len(lower_hull) == 1:
lower_hull[0][2] = -float('inf')
else:
line = get_line_from_two_points(lower_hull[0][0], lower_hull[1][0])
lower_hull[1][2] = get_primal_point(line)[0]
return lower_hull
# Maximise A[i] * B[i] + A[i] * B[j] + A[j] * B[j]
def f(A, B):
debug = False
if debug:
print("A: %s" % A)
print("B: %s" % B)
best = -float('inf')
best_idxs = ()
indexed_lines = [((A[i], A[i] * B[i]), i) for i in range(len(A))]
# Convert to points in the dual plane
# [dual_point, original_line, leftmost x coordinate added later, original index]
dual_points = [[get_dual_point(line), line, None, i] for line, i in indexed_lines]
# Sort points by x coordinate ascending
sorted_points = sorted(dual_points, key=lambda x: x[0][0])
if debug:
print("sorted points")
print(sorted_points)
# Build lower hull, left to right
lower_hull = []
add_right_to_lower_hull(lower_hull, sorted_points[0])
for i in range (1, len(sorted_points)):
# Query the point before inserting it
# because of the stipulation that i != j
idx = sorted_points[i][3]
segment_idx = get_segment_idx(lower_hull, B[idx])
m, b = lower_hull[segment_idx][1]
j = lower_hull[segment_idx][3]
candidate = m * B[idx] + b + A[idx] * B[idx]
if debug:
print("segment: %s, idx: %s, B[idx]: %s" % (segment_idx, idx, B[idx]))
if candidate > best:
best = candidate
best_idxs = (idx, j)
add_right_to_lower_hull(lower_hull, sorted_points[i])
if debug:
print("lower hull")
print(lower_hull)
# Build lower hull, right to left
lower_hull = collections.deque()
lower_hull.append(sorted_points[len(sorted_points) - 1])
for i in range (len(sorted_points) - 2, -1, -1):
# Query the point before inserting it
# because of the stipulation that i != j
idx = sorted_points[i][3]
segment_idx = get_segment_idx(lower_hull, B[idx])
m, b = lower_hull[segment_idx][1]
j = lower_hull[segment_idx][3]
candidate = m * B[idx] + b + A[idx] * B[idx]
if debug:
print("segment: %s, idx: %s, B[idx]: %s" % (segment_idx, idx, B[idx]))
if candidate > best:
best = candidate
best_idxs = (idx, j)
add_left_to_lower_hull(lower_hull, sorted_points[i])
if debug:
print("lower hull")
print(lower_hull)
return best, best_idxs
#A = [1, 9, 6, 6]
#B = [9, 1, 6, 6]
#print("")
#print(f(A, B))
# Test
import random
def brute_force(A, B):
best = -float('inf')
best_idxs = ()
for i in range(len(A)):
for j in range(len(B)):
if i != j:
candidate = A[i] * B[i] + A[i] * B[j] + A[j] * B[j]
if candidate > best:
best = candidate
best_idxs = (i, j)
return best, best_idxs
num_tests = 500
n = 20
m = 1000
for _ in range(num_tests):
A = [random.randint(1, m) for i in range(n)]
B = [random.randint(1, m) for i in range(n)]
_f = f(A, B)
_brute = brute_force(A, B)
if _f[0] != _brute[0]:
print("Mismatch")
print(A)
print(B)
print(_f, _brute)
print("Done testing.")

Yes, there’s an O(n log n)-time algorithm.
If we look at the function f(x) = max {a[i] b[i] + a[i] x | i},
it traces out a lower (convex) hull. It basically suffices to evaluate
f(b[j]) + a[j] b[j] for every j, with the one sticking point that
we need i ≠ j.
To fix that problem, we turn to an incremental hull algorithm with
amortized O(log n)-time insertions. The canonical algorithm keeps the
hull in sorted order, allowing for O(log n)-time queries. Starting with
an empty hull, for each index i, we query i and then insert i. Do this
once in forward order and once in reverse order, and take the max.

Related

Find the frequency of number repeates (r-l+1)/2 times in range [l:r]

Given the array: A[N]. There are some queries including Li and Ri. We must Find the number that appears more than (Ri-Li+1)/2 times in range [Li:Ri].
For example:
INPUT:
N=7
1 1 3 2 3 4 3
OUTPUT:
Ranges:
[1:3] ans is :>1
[1:4] no answer
[1:7] ans is :>3
[2:7] no answer
First, I think we can use map to store the times that A[i] appears from 1 to j
And it's take up a lot of memories if N up to 5e5.
Then I sort(Increasing order) the queries so that Ri, and no more idea.
Suggestions:
Is there any efficient algorithm to this problem or any data structure to stores the frequency of A[i]: from 1 to j?
I have no idea about such data structure, but I find an solution for this problem.
If Ri - Li + 1 is odd, there may have two elements appear (Ri - Li + 1) / 2 times. Which one do you want to get? We can use the algorithm beblow to get one of them and the algorithm can get all of these two if you want.
If there are just few queries satisfy \sum (Ri - Li) are small enough, get the answer for each [Li, Ri] separately.
For each [Li, Ri],we can use a O(Ri - Li) time, O(1) auxiliary memory algorithm to get the answer. If there is a x appears exactly (Ri - Li + 1) / 2 times, at least one of three case below must happend (suppose Ri > Li).
x appears (Ri - Li + 1) / 2 times in [Li, Ri - 1].
x appears (Ri - Li + 1) / 2 times in [Li + 1, Ri].
A[Li] == A[Ri] == x.
For case 1,2 we can use 'Heavy Hitters' algorithm to find the candidate x.
So can get three candidate x for one travese, and check each of them to find the answer(see cpp code below).
int getCandidateX(int L, int R) {
int x = A[L], count = 1;
for(int i = L + 1; i <= R; ++i){
if(A[i] == x) ++count;
else if(--count == 0){
x = A[i];
count = 1;
}
}
return x;
}
int getFrequency(int L, int R, int x) {
int count = 0;
for(int i = L; i <= R; ++i) {
if(A[i] == x) ++count;
}
return count;
}
/**
* if Ri == Li, no answer
* suppose Ri > Li
* return {x, 0} and {-1,-1} if no such element
*/
pair<int,int> getAnswer(int Li, int Ri) {
int t = (Ri - Li + 1) / 2;
int x;
if((Ri - Li) & 1) {
x = getCandidateX(Li, Ri);
if(getFrequency(Li, Ri, x) == t) return {x, 0};
return {-1, -1}
}
x = getCandidateX(Li, Ri - 1);
if(getFrequency(Li, Ri, x) == t) return {x, 0};
x = getCandidateX(Li + 1, Ri);
if(getFrequency(Li, Ri, x) == t) return {x, 0};
if(A[Li] == A[Ri] && getFrequency(Li, Ri, A[Li]) == t)
return {Li, 0};
return {-1,-1}
}
When \sum (Ri - Li) is large, I found an O((m + n)logn) online solution, but it also cost a lot of memory. I conduct it as a RMQ(Range Maximum Query) problem and solve it by ST(sparse table) algorithm.
First, we can get the frequency in [L, R] of any x with O(logn) time.
We can store all the position of x in map[x] where map maps x to its position array.(we can use treemap or hashmap)
Then we can get the frequency of x in [L, R] by binary search which cost O(logn) time.
Define num[L][R] be a set of elements appear more than (R - L + 1) / 4 times in interavl [L,R]. Let val[i][k] = num[L][L + 2^k - 1], k >= 2.
Every val[i][k] has at most 4 elements, and we can calculate all val[i][k] for 0 <= i <= n and i + 2^k <= n in O(nlogn) time and O(nlogn) memory.
Because for every interval [L,R] and M1, M2 such that L <= M < R it is obvious to see that num[L][R] \subset num[L][M] \cup num[M + 1][R]. Then val[i][k] \subset val[i][k - 1] \cup val[i + 2^{k - 1} - 1][k - 1]`.
Let t as the greatest number such that 2^t <= R - L + 1 we can draw a conclusion that if x \in [L,R] appears not less than (R - L + 1) / 2 times,x must in val[L][t] or val[R - 2^t + 1][R]。
This means it is sufficient to check the frequency of every element in val[L][t] \cup val[R - 2^t - 1][t].
For every query [L,R] we can check every element in O(logn) time, so the total time is O((m + n)logn) where n is the element number of A and m is the query number.
If the question is to get the element appears exactly (Ri-Li+1)/2 + 1 times (or more), it can be solve in a more simply way.

Given two arrays and an upper limit, what is the most efficient way to get the index pair for which the sum is maximum and below the upper limit?

Given two arrays A and B and an upper limit k, what will the most efficient way to compute the index pair (i, j) such that given,
s = A[i] + B[j]
s = max(A[a] + B[b]) for a = 0, 1, 2, .. , len(A)-1 and b = 0, 1, 2, .. , len(B)-1
and
s < k
For example,
Given,
A = [9,2,5]
B = [2,1,6]
k = 5
we get,
s = 2 + 2 = 4 < 5
and hence,
i = 1 and j = 0
So the output should be (1,0)
A straight-forward approach would be looping through all the elements of A and B but that would make the worst case time complexity O(nm) where n = len(A) and m = len(B).
Is there a better way to solve this problem?
This type of problems can be solved by sorting one of the array.
One Approach could be this ::
make an array temp of tuples such that each tuple will be (value,index) where value is item of B and index is its corresponding index in B.
Now, sort this temp array with respect to first item of tuple i.e, value.
iterate through array A and using Binary Search find the Lower bound of K - A[i] in temp array. let it be at index j.
Now there are two possibilities, either A[ i ] + temp[ j ][ 0 ] > = K or < k.
If it is greater than K, than check if j - 1 exists or not and update currentMaximum if possible because this pair can be max and at the same time less than k because we found lower bound.
If it is less than K, than update currentMaximum if possible.
If you need indices than whenever you update you currentMaximum, store i and j.
In this way you can find maximum sum of pairs such that it is less than K with original index as given in array B
If order of elements does not matter than, just sort B and do same steps on B instead of temp.
Time Complexity
For sorting = O( len(B) * Log(len(B)) )
for traversing A and doing Binary Search on B = O ( len(A) * Log (len(B))) i.e, O ( nlog(n))
You can use sort for A and B. Then you can use an early break once you are >= k. The function below returns indices, s.t. A[i] + B[j] < k and A[p] + B[q] < A[i] + B[j], for all p < i and for all q < j.
def sum_less_than_k(A, B, k):
i_max = -1
j_max = -1
s_max = -np.inf
for i, a in enumerate(A):
if a + B[0] >= k:
break
for j, b in enumerate(B):
if a + b >= k:
break
if a + b > s_max:
s_max = a + b
i_max = i
j_max = j
return i_max, j_max
A.sort()
B.sort()
i, j = sum_less_than_k(A, B, k)
I wrote the code for Saurab's suggestion as well which is way faster for large k relative to what's in the list. However, for rather short lists or small k the two for loops are faster according to some sample runs.
def sum_less_than_k(A, B, k):
i_max = j_max = -1
s_max = -np.inf
for i, a in enumerate(A):
j = bisect(B, k - a - 1)
if len(B) > j > -1 and k > A[i] + B[j] > s_max:
s_max = A[i] + B[j]
i_max = i
j_max = j
return i_max, j_max
B.sort()
i, j = sum_less_than_k(A, B, k)

Xor of all pairwise sums of integers in an array

We have an array A for example [1, 2, 3]. I want to find the XOR of the SUM of all pairs of integers in the array.
Though this can easily be done in O(n^2) (where n is the size of the array) by passing over all of the pairs, I want to improve the time complexity of the solution? Any answer that improves the time complexity would be great.
E.g. for the above example array, A, the answer would be (1+2)^(1+3)^(2+3) = 2. Since the pairwise elements are (1,2), (1,3), (2,3), and 3 ^ 4 ^ 5 = 2.
Here's an idea for a solution in O(nw) time, where w is the size of a machine word (generally 64 or some other constant). The most important thing is counting how many of the pairs will have a particular bit set, and the parity of this number determines whether that bit will be set in the result. The goal is to count that in O(n) time instead of O(n2).
Finding the right-most bit of the result is easiest. Count how many of the input numbers have a 0 in the right-most place (i.e. how many are even), and how many have a 1 there (i.e. how many are odd). The number of pairs whose sum has a 1 in the rightmost place equals the product of those two counts, since a pair must have one odd and one even number for its sum to be odd. The result has a 1 in the rightmost position if and only if this product is odd.
Finding the second-right-most bit of the result is a bit harder. We can do the same trick of counting how many elements do and don't have a 1 there, then taking the product of those counts; but we also need to count how many 1 bits are carried into the second place from sums where both numbers had a 1 in the first place. Fortunately, we can compute this using the count from the previous stage; it is the number of pairs given by the formula k*(k-1)/2 where k is the count of those with a 1 bit in the previous place. This can be added to the product in this stage to determine how many 1 bits there are in the second place.
Each stage takes O(n) time to count the elements with a 0 or 1 bit in the appropriate place. By repeating this process w times, we can compute all w bits of the result in O(nw) time. I will leave the actual implementation of this to you.
Here's my understanding of at least one author's intention for an O(n * log n * w) solution, where w is the number of bits in the largest sum.
The idea is to examine the contribution of each bit one a time. Since we are only interested in whether the kth bit in the sums is set in any one iteration, we can remove all parts of the numbers that include higher bits, taking them each modulo 2^(k + 1).
Now the sums that would necessarily have the kth bit set lie in the intervals, [2^k, 2^(k + 1)) and [2^(k+1) + 2^k, 2^(k+2) − 2]. So we sort the input list (modulo 2^(k + 1)), and for each left summand, we decrement a pointer to the end of each of the two intervals, and binary search the relevant start index.
Here's JavaScript code with a random comparison to brute force to show that it works (easily translatable to C or Python):
// https://stackoverflow.com/q/64082509
// Returns the lowest index of a value
// greater than or equal to the target
function lowerIdx(a, val, left, right){
if (left >= right)
return left;
mid = left + ((right - left) >> 1);
if (a[mid] < val)
return lowerIdx(a, val, mid+1, right);
else
return lowerIdx(a, val, left, mid);
}
function bruteForce(A){
let answer = 0;
for (let i=1; i<A.length; i++)
for (let j=0; j<i; j++)
answer ^= A[i] + A[j];
return answer;
}
function f(A, W){
const n = A.length;
const _A = new Array(n);
let result = 0;
for (let k=0; k<W; k++){
for (let i=0; i<n; i++)
_A[i] = A[i] % (1 << (k + 1));
_A.sort((a, b) => a - b);
let pairs_with_kth_bit = 0;
let l1 = 1 << k;
let r1 = 1 << (k + 1);
let l2 = (1 << (k + 1)) + (1 << k);
let r2 = (1 << (k + 2)) - 2;
let ptr1 = n - 1;
let ptr2 = n - 1;
for (let i=0; i<n-1; i++){
// Interval [2^k, 2^(k+1))
while (ptr1 > i+1 && _A[i] + _A[ptr1] >= r1)
ptr1 -= 1;
const idx1 = lowerIdx(_A, l1-_A[i], i+1, ptr1);
let sum = _A[i] + _A[idx1];
if (sum >= l1 && sum < r1)
pairs_with_kth_bit += ptr1 - idx1 + 1;
// Interval [2^(k+1)+2^k, 2^(k+2)−2]
while (ptr2 > i+1 && _A[i] + _A[ptr2] > r2)
ptr2 -= 1;
const idx2 = lowerIdx(_A, l2-_A[i], i+1, ptr2);
sum = _A[i] + _A[idx2]
if (sum >= l2 && sum <= r2)
pairs_with_kth_bit += ptr2 - idx2 + 1;
}
if (pairs_with_kth_bit & 1)
result |= 1 << k;
}
return result;
}
var As = [
[1, 2, 3], // 2
[1, 2, 10, 11, 18, 20], // 50
[10, 26, 38, 44, 51, 70, 59, 20] // 182
];
for (let A of As){
console.log(JSON.stringify(A));
console.log(`DP, brute force: ${ f(A, 10) }, ${ bruteForce(A) }`);
console.log('');
}
var numTests = 500;
for (let i=0; i<numTests; i++){
const W = 8;
const A = [];
const n = 12;
for (let j=0; j<n; j++){
const num = Math.floor(Math.random() * (1 << (W - 1)));
A.push(num);
}
const fA = f(A, W);
const brute = bruteForce(A);
if (fA != brute){
console.log('Mismatch:');
console.log(A);
console.log(fA, brute);
console.log('');
}
}
console.log("Done testing.");

Find the number of triplets i,j,k in an array such that the xor of elements indexed i to j-1 is equal to the xor of elements indexed j to k

For a given sequence of positive integers A1,A2,…,AN, you are supposed to find the number of triplets (i,j,k) such that Ai^Ai+1^..^Aj-1=Aj^Aj+1^..Ak
where ^ denotes bitwise XOR.
The link to the question is here: https://www.codechef.com/AUG19B/problems/KS1
All I did is try to find all subarrays with xor 0. The solution works but is quadratic time and thus too slow.
This is the solution that I managed to get to.
for (int i = 0; i < arr.length; i++) {
int xor = arr[i];
for (int j = i + 1; j < arr.length; j++) {
xor ^= arr[j];
if (xor == 0) {
ans += (j - i);
}
}
}
finAns.append(ans + "\n");
Here's an O(n) solution based on CiaPan's comment under the question description:
If xor of items at indices I through J-1 equals that from J to K, then xor from I to K equals zero. And for any such subarray [I .. K] every J between I+1 and K-1 makes a triplet satisfying the requirements. And xor from I to K equals (xor from 0 to K) xor (xor from 0 to I-1). So I suppose you might find xor-s of all possible initial parts of the sequence and look for equal pairs of them.
The function f is the main method. brute_force is used for validation.
Python 2.7 code:
import random
def brute_force(A):
res = 0
for i in xrange(len(A) - 1):
left = A[i]
for j in xrange(i + 1, len(A)):
if j > i + 1:
left ^= A[j - 1]
right = A[j]
for k in xrange(j, len(A)):
if k > j:
right ^= A[k]
if left == right:
res += 1
return res
def f(A):
ps = [A[0]] + [0] * (len(A) - 1)
for i in xrange(1, len(A)):
ps[i] = ps[i- 1] ^ A[i]
res = 0
seen = {0: (-1, 1, 0)}
for i in xrange(len(A)):
if ps[i] in seen:
prev_i, i_count, count = seen[ps[i]]
new_count = count + i_count * (i - prev_i) - 1
res += new_count
seen[ps[i]] = (i, i_count + 1, new_count)
else:
seen[ps[i]] = (i, 1, 0)
return res
for i in xrange(100):
A = [random.randint(1, 10) for x in xrange(200)]
f_A, brute_force_A = f(A), brute_force(A)
assert f_A == brute_force_A
print "Done"

Longest consecutive path in a matrix of letters

I'm trying to solve this problem:
Given a matrix of n * m, with letters(characters), find the longest consecutive path of letters in the matrix and output the string. For example:
m = [[a,c,d],[i,b,e],[h,g,f]]
result = e,f,g,h
You can only move up, down, left, right inside the matrix. This is what I have come up so far following some information online, but I'm not all the way there.
I would also like to make the solution efficient, my current code might have too many loops and is probably slow for a large matrix. Any help would be really appreciated!
R = len(matrix)
C = len(matrix[0])
x = [0, 1, 0, -1]
y = [1, 0, -1, 0]
dp=[[0 for i in range(C)]for i in range(R)]
def isvalid( i, j):
if (i < 0 or j < 0 or i >= R or j >= C):
return False
return True
def getLenUtil(matrix, i, j, prev):
if (isvalid(i, j)==False or isadjacent(prev, mat[i][j])==False):
return 0
if (dp[i][j] != -1):
return dp[i][j]
ans = 0
for k in range(4):
ans = max(ans, 1 + getLenUtil(mat, i + x[k],j + y[k], mat[i][j]))
dp[i][j] = ans
return dp[i][j]
def isadjacent(prev, curr):
if (ord(curr) -ord(prev)) == 1:
return True
return False
def findLongestSequence(matrix):
for i in range(R):
for j in range(C):
dp[i][j]=-1
ans = 0
for i in range(R):
for j in range(C):
if (mat[i][j] == s):
for k in range(4):
ans = max(ans, 1 + getLenUtil(matrix, i + x[k], j + y[k], s));
return ans
Several issues in your code:
mat and matrix spelling should be unified.
s is never initialised
In R = len(matrix) and several other references to mat or matrix, that variable is not defined. findLongestSequence is called with the actual value of matrix, so it is there there R should be defined, ...etc
Also,
it is easier if you don't pass prev, but the actual expected character (that is already "incremented").
Why first initialise dp with zeroes, when then you re-initialise with -1? Just use -1 immediately.
Here is how it could work:
def findLongestSequence(mat):
R = len(mat)
C = len(mat[0])
x = [0, 1, 0, -1]
y = [1, 0, -1, 0]
dp = [[-1 for i in range(C)] for i in range(R)]
def isvalid( i, j):
return (0 <= i < R) and (0 <= j < C)
def getLenUtil(mat, i, j, expected):
if not isvalid(i, j) or mat[i][j] != expected:
return 0
if dp[i][j] == -1:
ans = 0
expected = chr(ord(mat[i][j])+1)
for k in range(4):
ans = max(ans, 1 + getLenUtil(mat, i + x[k], j + y[k], expected))
dp[i][j] = ans
return dp[i][j]
ans = 0
for i in range(R):
for j in range(C):
getLenUtil(mat, i, j, mat[i][j])
ans = max(ans, max(dp[i]))
print(dp)
return ans
res = findLongestSequence([["a","c","d"],["i","b","e"],["h","g","f"]])
print(res)
Note that for this example data the returned answer is 8, not 4, as the longest sequence starts with "b" and ends with "i" -- 8 characters in total.

Resources