I approached the Longest Common Subsequence as:
LCS(m,n) = max( LCS(m-1,n), LCS(m,n-1), LCS(m-1,n-1) + (String1[m]==String2[n]) );
Whereas the texts show the logic for the problem to be like:
if( String1[m]==String2[n] )
LCS(m,n) = LCS(m-1,n-1) + 1;
else LCS(m,n) = max( LCS(m-1,n), LCS(m,n-1) );
Will my approach produce incorrect results? if yes, then in what kind of a situation? If it is correct, how do you justify the correctness?
Thanks in advance!
My (badly) Java version, it runs correctly?
//'main' method must be in a class 'Rextester'.
//Compiler version 1.8.0_111
import java.util.*;
import java.lang.*;
class Rextester
{
public static void main(String args[])
{
int[] a = {1,1,1,1,2,3,2,3};
int[] b = {1,1,1,1,3,4,3,4};
System.out.println(solve(a, b).toString());
System.out.println(solve2(a, b).toString());
}
private static void printL(int[][]len, int m, int n, int[] a, int[] b)
{
System.out.print(" a→ ");
for (int j = 0; j < m; ++j)
{
System.out.print(a[j]);
System.out.print(" ");
}
System.out.println();
for (int i = 0; i <= n; ++i)
{
if (i > 0) { System.out.print(" "); System.out.print(b[i-1]); System.out.print(" "); }
else { System.out.print("b↓ "); }
for (int j = 0; j <= m; ++j)
{
System.out.print(len[i][j]);
System.out.print(" ");
}
System.out.println();
}
}
private static List<Integer> solve(int[] a, int[] b)
{
int m = a.length;
int n = b.length;
System.out.println("Method 1");
int[][] len = new int[n+1][m+1];
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
len[i+1][j+1] = a[j] == b[i] ? 1 + len[i][j] : Math.max(len[i+1][j], len[i][j+1]);
printL(len, m, n, a, b);
List<Integer> c = new ArrayList<Integer>();
for (int i = n - 1, j = m - 1; len[i+1][j+1] > 0;)
{
if (a[j] == b[i]) { c.add(a[j]); i--; j--; }
else if (len[i+1][j] < len[i][j+1]) i--;
else j--;
}
Collections.reverse(c);
return c;
}
private static List<Integer> solve2(int[] a, int[] b)
{
int m = a.length;
int n = b.length;
System.out.println("Method 2");
int[][] len = new int[n+1][m+1];
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
len[i+1][j+1] = Math.max(Math.max(len[i+1][j], len[i][j+1]), (a[j] == b[i] ? 1 : 0) + len[i][j]);
printL(len, m, n, a, b);
List<Integer> c = new ArrayList<Integer>();
for (int i = n - 1, j = m - 1; len[i+1][j+1] > 0;)
{
if (a[j] == b[i]) { c.add(a[j]); i--; j--; }
else if (len[i+1][j] < len[i][j+1]) i--;
else j--;
}
Collections.reverse(c);
return c;
}
}
output on rextester:
Method 1
a→ 1 1 1 1 2 3 2 3
b↓ 0 0 0 0 0 0 0 0 0
1 0 1 1 1 1 1 1 1 1
1 0 1 2 2 2 2 2 2 2
1 0 1 2 3 3 3 3 3 3
1 0 1 2 3 4 4 4 4 4
3 0 1 2 3 4 4 5 5 5
4 0 1 2 3 4 4 5 5 5
3 0 1 2 3 4 4 5 5 6
4 0 1 2 3 4 4 5 5 6
[1, 1, 1, 1, 3, 3]
Method 2
a→ 1 1 1 1 2 3 2 3
b↓ 0 0 0 0 0 0 0 0 0
1 0 1 1 1 1 1 1 1 1
1 0 1 2 2 2 2 2 2 2
1 0 1 2 3 3 3 3 3 3
1 0 1 2 3 4 4 4 4 4
3 0 1 2 3 4 4 5 5 5
4 0 1 2 3 4 4 5 5 5
3 0 1 2 3 4 4 5 5 6
4 0 1 2 3 4 4 5 5 6
[1, 1, 1, 1, 3, 3]
My sketchy proof:
If you look at any row LCS(m) in the table above, you'll see that they all have increasing values, or they're all monotonically increasing. They cannot be decreasing since LCS(m,n) means longest common subsequence of (sub)string1 of length m and (sub)string2 of length n, if n2 >= n1 then LCS(m,n2) >= LCS(m,n1) because if n2 >= n1, LCS(m,n2) contains LCS(m,n1).
For the column LCS(n) you use the same proof. Now you have LCS(m,n) <= LCS(m,n+1) and LCS(m,n) <= LCS(m+1,n), which means your taking maximum of all three possible cases are correct.
LCS(m,n) = max( LCS(m-1,n), LCS(m,n-1), LCS(m-1,n-1) + (String1[m]==String2[n]) );
takes the wrong path only when String1[m] != String2[n] and (LCS(m-1,n-1) > LCS(m,n-1) or LCS(m-1,n-1) > LCS(m-1,n)), but the latter case (LCS(m-1,n-1) > LCS(m,n-1) or LCS(m-1,n-1) > LCS(m-1,n)) never happens. So your approach is correct.
I would like to know how to output multiple lines from a for loop.
For example, if I want to input a number of subsequent lines N and then another numbers. I am trying to output the inputs that I provided below, but whenever I do this it keeps returning only the last digits and not everything I entered.
This is what I know so far.
#include <iostream>
using namespace std;
int main()
{
int N, M, num;
cin >> N;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < 3; j++)
{
cin >> M;
for (int k = 0; k < M; k++)
cout << M << endl;
}
}
return 0;
}
Input:
2 (This is for N)
1 2 3
4 5 6
or
3
10 20 30
50 100 500
1000 5 0
---------
Output:
1 2 3
4 5 6
10 20 30
50 100 500
1000 5 0
A matrix B (consisting of integers) of dimension N × N is said to be good if there exists an array A (consisting of integers) such that B[i][j] = |A[i] - A[j]|, where |x| denotes absolute value of integer x.
You are given a partially filled matrix B of dimension N × N. Q of the entries of this matrix are filled by either 0 or 1. You have to identify whether it is possible to fill the remaining entries of matrix B (the entries can be filled by any integer, not necessarily by 0 or 1) such that the resulting fully filled matrix B is good.
Example
Input 4
2 2
1 1 0
1 2 1
2 3
1 1 0
1 2 1
2 1 0
3 2
2 2 0
2 3 1
3 3
1 2 1
2 3 1
1 3 1
Output
yes
no
yes
no
Here is my code, but failing some tests.
include int main(){
int t;
scanf("%d", &t);
while(t--){
int n, q;
scanf("%d %d", &n, &q);
int arr[n][n];
int brr[n];
for(int i=0;i<n;i++){
brr[i]=1;
for(int j=0;j<n;j++)
arr[i][j]=-1;
}
int result=0;
while(q--){
int l, r, val;
scanf("%d %d %d", &l, &r, &val);
arr[l-1][r-1]=val;
arr[r-1][l-1]=val;
if( abs(brr[l-1]-brr[r-1])!=val && l!=r){
brr[r-1]=brr[r-1]-val;
}
}
for(int i=0;i<n;i++)
printf("%d ", brr[i]);
printf("\n");
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(arr[i][j]!=-1 ){
if( abs(brr[i]-brr[j])==arr[i][j] && abs(brr[i]-brr[j])==arr[j][i]){
continue;
}
else{
result=1;
break;
}
}
}
if(result)
break;
}
if(result)
printf("no\n");
else
printf("yes\n");
}
return 0; }
The question is from live contest : https://www.codechef.com/SEPT17/problems/FILLMTR/. Please focus on learning rather than increase the count of accepted problems.
Hi I'v been trying to write Hoare's partition function for like 5 hours now. I read this and this and even straight up copied the "correct" function from these questions and it's still nowhere near the answer. Here is my "translated" code from Cormen's book.
int Hpartition(int A[], int p, int r){
int x = A[p];
int i = p - 1;
int j = r + 1;
while(true){
do{
j--;
}while(A[j] <= x);
do{
i++;
}while(A[i] >= x);
if(i < j){
swap(A[i],A[j]);
}
else
return j;
}
}
QuickSort:
void qs(int A[],int p,int r){
if(p<r){
int q=Hpartition(A,p,r);
qs(A,p,q-1);
qs(A,q+1,r);
}
}
Main:
int main(int argc, const char * argv[]) {
int tab[10];
for(int k=0;k<10;k++){
cin >> tab[k];
}
qs(tab,0,9);
for(int i=0;i<10;i++){
cout << tab[i] << " ";
}
return 0;
}
For this data :
2 4 1 3 5 7 6 8 10 9
It produces this result:
2 4 9 3 5 7 6 8 10 1
Based on the previous questions regarding the topic I know there may be some mistakes in the book. But even when I apply the answers from the previous questions it just won't work .
Here is the algorithm from the book:
HOARE-PARTITION(A, p, r)
1 x = A[p]
2 i = p - 1
3 j = r + 1
4 while TRUE
5 repeat
6 j = j - 1
7 until A[j] <= x
8 repeat
9 i = i + 1
10 until A[i] >= x
11 if i < j
12 exchange A[i] with A[j]
13 else return j
Thanks in advance for any help.
You have 2 error translating code from book:
do{
j--;
}while(A[j] <= x);
You should inverse this:
do{
j--;
}while(A[j] > x);
The same with:
do{
i++;
}while(A[i] >= x);
And one more here:
qs(A,p,q-1);
qs(A,q+1,r);
Change to:
qs(A,p,q);
qs(A,q+1,r);
I have to get the desired output as follows:
1
2 6
3 7 10
4 8 11 13
5 9 12 14 15
But I can't seem to figure out how to do it. All I get is:
1
2 6
3 7 6
4 8 7 6
5 9 8 7 6
Here is my code:
#include<stdio.h>
int main()
{
int n,i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
for(j=0;j<i;j++)
{
if((j+1)==1)
printf("%d ",i);
else
printf("%d ",i+n-j);
}
printf("\n");
}
return 0;
}
But I understood the desired output:
I have to print the numbers from 1 to 15 in ascending order like a right angled triangle.
#include <stdio.h>
#define SZ 5
int main()
{
int i,j, add = SZ, val[SZ+1] = {1};
for( j=1; j<=SZ; ++j )
{
for( i=0; i<j; ++i )
printf( "%2d ", val[i]++ );
printf( "\n" );
val[j] = val[j-1] + --add;
}
}