Longest common subsequence difference - java

I have a program that I am writing in Java and have to do 2 things, find the longest common sub-sequence and align the common characters. The LCS works just fine but the align part just loops away or do nothing.
I try to do this algorithm which I found on Wikipedia
function printDiff(C[0..m,0..n], X[1..m], Y[1..n], i, j)
if i > 0 and j > 0 and X[i] = Y[j]
printDiff(C, X, Y, i-1, j-1)
print " " + X[i]
else if j > 0 and (i = 0 or C[i,j-1] ≥ C[i-1,j])
printDiff(C, X, Y, i, j-1)
print "+ " + Y[j]
else if i > 0 and (j = 0 or C[i,j-1] < C[i-1,j])
printDiff(C, X, Y, i-1, j)
print "- " + X[i]
else
print ""
Here is the code I wrote (I removed the LCS part)
static char[] input1 = "ABCDE".toCharArray();
static char[] input2 = "ACDC".toCharArray();
static int M = input1.length;
static int N = input2.length;
static int[][] opt = new int[M + 1][N + 1];
public static void printDiff(int opt[][], char input1[], char input2[]) {
int i = 0, j = 0;
while (i < input1.length && j < input2.length) {
if (i > 0 && j > 0 && input1[i] == input2[j]) {
System.out.print(" " + input1[i]);
i++;
j++;
} else if (j > 0 && (i == 0 || opt[i][j - 1] >= opt[i - 1][j])) {
System.out.print("+ " + input2[j]);
j++;
} else if (i > 0 && (j == 0 || opt[i][j - 1] < opt[i - 1][j])) {
System.out.print("- " + input1[i]);
i++;
} else {
System.out.print("");
}
}
}

I rewrote your code to use the Wikipedia algorithm. In other words, I used recursion rather than a where clause. I had to change one of the if conditions because Java is zero index based and the Wikipedia algorithm is one index based.
I had to add the LCS function back in so that I could calculate the int[][]opt.
I added parenthesis to the if statements to make sure that the operations were done in the order I wanted them done.
I also fixed the output. The Wikipedia algorithm had "+ " and "- " as output. That appears to be a typo. The output should be " +" and " -", respectively.
Here's my version of the code.
public class PrintDiff {
char[] input1 = "ABCDE".toCharArray();
char[] input2 = "ACDC".toCharArray();
int M = input1.length;
int N = input2.length;
public void run() {
int[][] opt = lcsLength(input1, input2);
printDiff(opt, input1, input2, M - 1, N - 1);
}
public int[][] lcsLength(char[] input1, char[] input2) {
int[][] opt = new int[M][N];
for (int i = 1; i < input1.length; i++) {
for (int j = 1; j < input2.length; j++) {
if (input1[i] == input2[j]) {
opt[i][j] = opt[i - 1][j - 1] + 1;
} else {
opt[i][j] = Math.max(opt[i][j - 1], opt[i - 1][j]);
}
}
}
return opt;
}
public void printDiff(int opt[][], char input1[], char input2[], int i,
int j) {
if ((i >= 0) && (j >= 0) && (input1[i] == input2[j])) {
printDiff(opt, input1, input2, i - 1, j - 1);
System.out.print(" " + input1[i]);
} else if ((j > 0) && ((i == 0) || (opt[i][j - 1] >= opt[i - 1][j]))) {
printDiff(opt, input1, input2, i, j - 1);
System.out.print(" +" + input2[j]);
} else if ((i > 0) && ((j == 0) || (opt[i][j - 1] < opt[i - 1][j]))) {
printDiff(opt, input1, input2, i - 1, j);
System.out.print(" -" + input1[i]);
} else {
System.out.print("");
}
}
public static void main(String[] args) {
new PrintDiff().run();
}
}
And here's my output.
A -B C D -E +C

Here is a version which returns the diffs of all the longest common subsequences (basically backtracks using the cached table - similar to the approach taken to get to all longest common subsequences in All Longest Common Subsequences) (or, you may refer to my blog#: http://codingworkout.blogspot.com/2014/07/longest-common-subsequence.html)
for ex, for GAC and AGCAT, it returns => { { "[G][A]C", "[G]A[C]", "G[A][C]" }, {"A[G]C[A]T", "A[G][C]AT", "[A]G[C]AT"} where GA, GC and AC are longest common subsequences...
string[][] GetDiffs(string A, string B, int aIndex, int bIndex,
int[][] DP_LCS_AllPrefixes_Cache)
{
if((aIndex == 0) && (bIndex ==0))
{
return null;
}
if (DP_LCS_AllPrefixes_Cache[aIndex][bIndex] == 0)
{
var r = new string[2][];
r[0] = new string[] { A.Substring(0, aIndex) };
r[1] = new string[] { B.Substring(0, bIndex) };
return r;
}
if (A[aIndex - 1] == B[bIndex - 1])
{
var r = this.GetDiffs(A, B, aIndex - 1, bIndex - 1,
DP_LCS_AllPrefixes_Cache);
string ch = string.Format("[{0}]", A[aIndex - 1]);
if (r == null)
{
r = new string[2][];
r[0] = new string[] { ch };
r[1] = new string[] { ch };
}
else
{
r[0] = r[0].Select(s => s + ch).ToArray();
r[1] = r[1].Select(s => s + ch).ToArray();
}
return r;
}
int lcs_up_direction = DP_LCS_AllPrefixes_Cache[aIndex - 1][bIndex];
int lcs_left_direction = DP_LCS_AllPrefixes_Cache[aIndex][bIndex - 1];
string[][] lcs_up = null, lcs_left = null;
if (lcs_up_direction == lcs_left_direction)
{
lcs_up = this.GetDiffs(A, B, aIndex - 1, bIndex,
DP_LCS_AllPrefixes_Cache);
lcs_left = this.GetDiffs(A, B, aIndex, bIndex - 1,
DP_LCS_AllPrefixes_Cache);
}
else if (lcs_up_direction > lcs_left_direction)
{
lcs_up = this.GetDiffs(A, B, aIndex - 1, bIndex,
DP_LCS_AllPrefixes_Cache);
}
else
{
lcs_left = this.GetDiffs(A, B, aIndex, bIndex - 1, DP_LCS_AllPrefixes_Cache);
}
char a = A[aIndex - 1], b = B[bIndex - 1];
string[][] rl = new string[2][];
rl[0] = new string[0];
rl[1] = new string[0];
if(lcs_up != null)
{
//we moved upward, that is we accepted that they differ with 'A' at aIndex-1 (a)
rl[0] = lcs_up[0].Select(s => s + a.ToString()).ToArray();
rl[1] = lcs_up[1];
}
if (lcs_left != null)
{
//we moved left, that is we accepted that they differ with 'B' at bIndex-1 (b)
rl[0] = rl[0].Union(lcs_left[0]).ToArray(); ;
rl[1] = rl[1].Union(lcs_left[1].Select(s => s + b.ToString())).ToArray();
}
return rl.ToArray();
}
where the caller is
string[][] GetDiffs(string A, string B, int[][] DP_LCS_AllPrefixes_Cache)
{
var r = this.GetDiffs(A, B, A.Length, B.Length,
DP_LCS_AllPrefixes_Cache);
return r;
}
And the DP method which captures LCS lengths to backtrack
public int[][] LCS_OfAllPrefixes_Length(string A, string B)
{
A.ThrowIfNullOrWhiteSpace("a");
B.ThrowIfNullOrWhiteSpace("b");
int[][] DP_LCS_AllPrefixes_Cache = new int[A.Length+1][];
for(int i = 0;i<DP_LCS_AllPrefixes_Cache.Length; i++)
{
DP_LCS_AllPrefixes_Cache[i] = new int[B.Length + 1];
}
for (int rowIndexOfCache = 1; rowIndexOfCache <= A.Length; rowIndexOfCache++)
{
for (int columnIndexOfCache = 1; columnIndexOfCache <= B.Length; columnIndexOfCache++)
{
//LCS(Ai, Bj) = 0 if i <=0, or j <= 0
// LCS(Ai, Bj) + 1 if Ai == Bj
// Max(LCS(Ai-1, Bj), LCS(Ai, Bj-1))
if(A[rowIndexOfCache-1] == B[columnIndexOfCache-1])
{
DP_LCS_AllPrefixes_Cache[rowIndexOfCache][columnIndexOfCache] = DP_LCS_AllPrefixes_Cache[rowIndexOfCache - 1][columnIndexOfCache - 1] + 1;
}
else
{
DP_LCS_AllPrefixes_Cache[rowIndexOfCache][columnIndexOfCache] = Utilities.Max(DP_LCS_AllPrefixes_Cache[rowIndexOfCache - 1][columnIndexOfCache],
DP_LCS_AllPrefixes_Cache[rowIndexOfCache][columnIndexOfCache - 1]);
}
}
}
return DP_LCS_AllPrefixes_Cache;
}
TestMethod
[TestMethod]
public void LCS_Tests()
{
string A = "GAC", B = "AGCAT";
var DP_LCS_AllPrefixes_Cache = this.LCS_OfAllPrefixes_Length(A, B);
Assert.IsTrue(DP_LCS_AllPrefixes_Cache[A.Length][B.Length] == 2);
var lcs_sequences = this.GetLongestCommonSubsequences(A, B, DP_LCS_AllPrefixes_Cache);
Assert.IsNotNull(lcs_sequences);
var diffs = this.GetDiffs(A, B, DP_LCS_AllPrefixes_Cache);
Assert.IsNotNull(diffs);
Assert.IsTrue(diffs.Length == 2);
Assert.IsTrue(diffs[0].Length == lcs_sequences.Length);
Assert.IsTrue(diffs[1].Length == lcs_sequences.Length);
Assert.IsTrue(lcs_sequences.Any(s => "AC".Equals(s)));
Assert.IsTrue(lcs_sequences.Any(s => "GC".Equals(s)));
Assert.IsTrue(lcs_sequences.Any(s => "GA".Equals(s)));
var DP_LCS_AllPrefixes_Subsequences_Cache = this.LCS_OfAllPrefixes_Subsequences(A, B);
Assert.IsTrue(DP_LCS_AllPrefixes_Subsequences_Cache[A.Length][B.Length].Length == 2);
Assert.IsTrue(DP_LCS_AllPrefixes_Subsequences_Cache[A.Length][B.Length].Subsequences
.Any(s => "AC".Equals(s)));
Assert.IsTrue(DP_LCS_AllPrefixes_Subsequences_Cache[A.Length][B.Length].Subsequences
.Any(s => "GC".Equals(s)));
Assert.IsTrue(DP_LCS_AllPrefixes_Subsequences_Cache[A.Length][B.Length].Subsequences
.Any(s => "GA".Equals(s)));
A = "ABCDGH"; B = "AEDFHR";
DP_LCS_AllPrefixes_Cache = this.LCS_OfAllPrefixes_Length(A, B);
Assert.IsTrue(DP_LCS_AllPrefixes_Cache[A.Length][B.Length] == 3);
lcs_sequences = this.GetLongestCommonSubsequences(A, B, DP_LCS_AllPrefixes_Cache);
Assert.IsNotNull(lcs_sequences);
diffs = this.GetDiffs(A, B, DP_LCS_AllPrefixes_Cache);
Assert.IsNotNull(diffs);
Assert.IsTrue(diffs.Length == 2);
Assert.IsTrue(diffs[0].Length == lcs_sequences.Length);
Assert.IsTrue(diffs[1].Length == lcs_sequences.Length);
Assert.IsTrue(lcs_sequences.Any(s => "ADH".Equals(s)));
DP_LCS_AllPrefixes_Subsequences_Cache = this.LCS_OfAllPrefixes_Subsequences(A, B);
Assert.IsTrue(DP_LCS_AllPrefixes_Subsequences_Cache[A.Length][B.Length].Length == 3);
Assert.IsTrue(DP_LCS_AllPrefixes_Subsequences_Cache[A.Length][B.Length].Subsequences
.Any(s => "ADH".Equals(s)));
A = "AGGTAB"; B = "GXTXAYB";
DP_LCS_AllPrefixes_Cache = this.LCS_OfAllPrefixes_Length(A, B);
Assert.IsTrue(DP_LCS_AllPrefixes_Cache[A.Length][B.Length] == 4);
lcs_sequences = this.GetLongestCommonSubsequences(A, B, DP_LCS_AllPrefixes_Cache);
Assert.IsNotNull(lcs_sequences);
diffs = this.GetDiffs(A, B, DP_LCS_AllPrefixes_Cache);
Assert.IsNotNull(diffs);
Assert.IsTrue(diffs.Length == 2);
Assert.IsTrue(diffs[0].Length == 2);
Assert.IsTrue(diffs[1].Length == lcs_sequences.Length);
Assert.IsTrue(lcs_sequences.Any(s => "GTAB".Equals(s)));
DP_LCS_AllPrefixes_Subsequences_Cache = this.LCS_OfAllPrefixes_Subsequences(A, B);
Assert.IsTrue(DP_LCS_AllPrefixes_Subsequences_Cache[A.Length][B.Length].Length == 4);
Assert.IsTrue(DP_LCS_AllPrefixes_Subsequences_Cache[A.Length][B.Length].Subsequences
.Any(s => "GTAB".Equals(s)));
A = "ABCDEF"; B = "UVWXYZ";
DP_LCS_AllPrefixes_Cache = this.LCS_OfAllPrefixes_Length(A, B);
Assert.IsTrue(DP_LCS_AllPrefixes_Cache[A.Length][B.Length] == 0);
lcs_sequences = this.GetLongestCommonSubsequences(A, B, DP_LCS_AllPrefixes_Cache);
diffs = this.GetDiffs(A, B, DP_LCS_AllPrefixes_Cache);
Assert.IsNotNull(diffs);
Assert.IsTrue(diffs.Length == 2);
Assert.IsTrue(diffs[0].Length == 1);
Assert.IsTrue(diffs[1].Length == 1);
}

Related

How can i print path to matrix path in java?

code is here
public class MatrixPath {
public static void main(String[] args) throws FileNotFoundException {
int m[][], c[][];
int set;
Scanner scan = new Scanner(new File("hw9_1.text"));
set = scantiness();
m = new int[set][set];
c = new int[set][set];
for (int i = 0; i < set; i++) {
for (int j = 0; j < set; j++) {
m[i][j] = scan.nextInt();
}
}
c[0][0] = m[0][0];
System.out.println(set);
for (int i = 0; i < set; i++) {
for (int j = 0; j < set; j++) {
System.out.print(m[i][j] + " ");
}
System.out.println();
}
System.out.println(path(m, set - 1, set - 1, c));
}
private static int path(int[][] m, int i, int j, int[][] c) {
if (i == 0 && j == 0) {
return c[0][0];
}
if (i == 0) {
c[i][j] = (c[0][j - 1] != 0) ? (c[0][j - 1] + m[0][j]) : (path(m, 0, j - 1, c) + m[0][j]);
return c[i][j];
}
if (j == 0) {
c[i][j] = (c[i - 1][0] != 0) ? (c[i - 1][0] + m[i][0]) : (path(m, i - 1, 0, c) + m[i][0]);
return c[i][j];
}
int A = (c[i - 1][j] != 0) ? (c[i - 1][j]) : (path(m, i - 1, j, c));
int B = (c[i][j - 1] != 0) ? (c[i][j - 1]) : (path(m, i, j - 1, c));
int C = (c[i - 1][j - 1] != 0) ? (c[i - 1][j - 1]) : (path(m, i - 1, j - 1, c));
c[i][j] = Math.max(A, Math.max(B, C)) + m[i][j];
System.out.print("(" + i + " " + j + ")");
return c[i][j];
}
}
I used the translator.
Code that utilizes dynamic programming to find the matrix path at its maximum value.
I can get the maximum value by executing the current code.
Text documents leverage the following:
4
1 1 1 1
2 -3 1 -5
-1 2 3 1
1 1 4 1
I want to track the path of the matrix to get the maximum value.
like this ->
max : 13
path : 0 0 > 1 0 > 2 1 > 2 2 > 3 2 > 3 3
Do I need to add a new method?
Or is it possible with the existing code?

I get java.lang.StringIndexOutOfBoundsException when translating c++ code into java code

I'm trying to solve this problem
https://vjudge.net/problem/UVALive-6805
I found solution but in c++ , Can anybody help me converting it to java code. I'm very newbie to programming
I tried a lot of solutions but non of them work.
Please I need help in this if possible
I don't know for example what is the equivalent for .erase function in c++ in java
Also is is sbstr in c++ provide different result from java ?
#include <iostream>
#include <string>
using namespace std;
int syllable(string word)
{
int L = word.size();
int syllable;
if (L>=7)
{
syllable = 3;
}
else if (L==6)
{
int indicator = 0;
for (int k=0; k<=L-2; k++)
{
string subword = word.substr(k, 2);
if (subword == "ng" || subword == "ny")
{
indicator++;
}
}
if (indicator == 0)
{
syllable = 3;
}
else
{
syllable = 2;
}
}
else if (L == 4 || L == 5)
{
syllable = 2;
}
else if (L == 3)
{
char Char = word[0];
if (Char=='a' || Char=='A' || Char=='e' || Char=='E' || Char=='i' || Char=='I' || Char=='o' || Char=='O' || Char=='u' || Char=='U')
{
syllable = 2;
}
else
{
syllable = 1;
}
}
else
{
syllable = 1;
}
return syllable;
}
int main()
{
string word;
int T;
cin >> T;
for (int i=1; i<=T; i++)
{
int syl[] = {0, -1, -2, -3};
string rhy[] = {"a", "b", "c", "d"};
int verse = 0;
int stop = 0;
while (stop == 0)
{
cin >> word;
int L = word.size();
char end = word[L-1];
if (end == '.')
{
stop = 1;
}
if (word[L-1] == ',' || word[L-1] == '.')
{
word = word.erase(L-1, 1);
L = word.size();
}
if (verse<=3)
{
syl[verse] = syl[verse] + syllable(word);
}
if (end == ',' || end == '.')
{
if (verse<=3)
{
rhy[verse] = word.substr(L-2, 2);
}
verse++;
if (verse<=3)
{
syl[verse] = 0;
}
}
}
int A = 0, B = 0, C = 0, D = 0;
for (int k=0; k<4; k++)
{
if (syl[k] >= 8 && syl[k] <= 12)
{
A = A + 10;
}
}
for (int k=0; k<2; k++)
{
if (rhy[k] == rhy[k+2])
{
B = B + 20;
}
}
for (int k=0; k<2; k++)
{
if (syl[k] == syl[k+2])
{
C = C + 10;
}
}
if (verse > 4)
{
D = (verse - 4) * 10;
}
int E = A + B + C - D;
cout << "Case #" << i << ": " << A << " " << B << " " << C << " " << D << " " << E << endl;
}
}
here is my trying
import java.util.*;
public class First {
public static int syllable(String word) {
int L = word.length();
int syllable;
if (L >= 7) {
syllable = 3;
} else if (L == 6) {
int indicator = 0;
for (int k = 0; k < L - 3; k++) {
String subword = word.substring(k, 2);
if (subword == "ng" || subword == "ny") {
indicator++;
}
}
if (indicator == 0) {
syllable = 3;
} else {
syllable = 2;
}
} else if (L == 4 || L == 5) {
syllable = 2;
} else if (L == 3) {
char Char = word.charAt(0);
if (Char == 'a' || Char == 'A' || Char == 'e' || Char == 'E' || Char == 'i' || Char == 'I' || Char == 'o'
|| Char == 'O' || Char == 'u' || Char == 'U') {
syllable = 2;
} else {
syllable = 1;
}
} else {
syllable = 1;
}
return syllable;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String word;
int T;
T = sc.nextInt();
for (int i = 1; i <= T; i++) {
int syl[] = { 0, -1, -2, -3 };
String rhy[] = { "a", "b", "c", "d" };
int verse = 0;
int stop = 0;
while (stop == 0) {
word = sc.next();
int L = word.length();
char end = word.charAt(L-1);
if (end == '.') {
stop = 1;
}
if (word.charAt(L-1) == ',' || word.charAt(L-1) == '.') {
word.substring(L-1, 1);
L = word.length();
}
if (verse <= 3) {
syl[verse] = syl[verse] + syllable(word);
}
if (end == ',' || end == '.') {
if (verse <= 3) {
rhy[verse] = word.substring(L - 2, 2);
}
verse++;
if (verse <= 3) {
syl[verse] = 0;
}
}
}
int A = 0, B = 0, C = 0, D = 0;
for (int k = 0; k < 4; k++) {
if (syl[k] >= 8 && syl[k] <= 12) {
A = A + 10;
}
}
for (int k = 0; k < 2; k++) {
if (rhy[k] == rhy[k + 2]) {
B = B + 20;
}
}
for (int k = 0; k < 2; k++) {
if (syl[k] == syl[k + 2]) {
C = C + 10;
}
}
if (verse > 4) {
D = (verse - 4) * 10;
}
int E = A + B + C - D;
System.out.println("Case #" + i + ": " + A + " " + B + " " + C + " " + D + " " + E);
}
}
}
The Exception is thrown by your second and your third call of String substring method. Your beginIndex is higher than your endIndex. As you can see in here https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int,%20int) beginIndex always has to be lower than the endIndex.
Before answering your question, there are some important points to mention in regards to Strings and Java in general.
Strings are immutable (This also applies to C++). This means that no method called on a String will change it, and that all methods simply return new versions of the original String with the operations done on it
The substring method in java has two forms.
One takes in beginIndex and returns everything from beginIndex to str.length() - 1 (where str represents a String)
The other takes in the beginIndex, and the endIndex, and returns everything from beginIndex to endIndex - 1. The beginIndex should never be larger than endIndex otherwise it throws an IndexOutOfBoundsException
C++'s substring method (string::substr()) takes in the beginning "index" and takes in the number of characters after it to include in the substring. So by doing substr(L-2, 2) you get the last two characters of the string.
Java will never allow you to go out of bounds. That means you need to constantly check whether you are within the bounds of anything you are iterating through.
With all this in mind, I would go and verify that all of the substring() method calls are returning the proper range of characters, and that you are properly reassigning the values returned from substring() to the proper variable.
To mimic C++'s string::erase(), depending on what part of the word you want to erase, you want to get the substring of the part before and the substring of the part after it and add them together.
Ex. Lets say I have a String line = "I do not like the movies"; Since it is impossible for anyone to not like movies, we want to cut out the word not
We do this by doing what I said above
String before = line.substring(0, 5); // This gives us "I do " since it goes up to but not including the 5th index.
String after = line.substring(5 + 3); // This gives us the rest of the string starting after the word "not" because not is 3 characters long and this skips to the 3rd index after index 5 (or index 8)
line = before + after; // This'll add those two Strings together and give you "I do like the movies"
Hope this helps!

Big integer multiplication in java

This is my own method and I am also using my own BigInt class I did everything but I cannot seem to find out where I am doing wrong if someone can help me, I will be really thankful.
public BigInt mul(BigInt o) {
int max = n.length > o.n.length ? n.length : o.n.length;
int[] newdigits = new int[n.length + o.n.length];
for (int i = 0; i < max; i++)
{
int carry = 0;
for (int i2 = 0; i2 < o.n.length || carry > 0; i2++)
{
int otherDigit = i2 >= o.n.length ? 0: o.n[i2];
int val = (n[i] * otherDigit) + carry;
newdigits[i + i2] += val % 10;
carry = val / 10;
}
}
return new BigInt(newdigits);
}
This is my code so far it works but in the result i get one extra zero, as an example: when i multiply 100*10 I get 01000 instead of 1000 and other issue is that when i multiply 9999*1999 I get this: 1817262619101 but the correct answer is 19988001.
Can some one help me on this?
Here is my BigInt class:
public class BigInt {
public static void main(String[] args) {
BigInt a = new BigInt(args.length == 2 ? args[0] : "9999");
BigInt b = new BigInt(args.length == 2 ? args[1] : "1999");
System.out.println(a + (a.equals(b) ? " equals " : " does not equal ") + b);
System.out.println(a + (a.compareTo(b) < 0 ? " < " : (a.compareTo(b) > 0 ? " > " : " = ")) + b);
System.out.println(a + " + " + b + " = " + a.add(b));
if (a.compareTo(b) >= 0) {
System.out.println(a + " - " + b + " = " + a.sub(b));
}
System.out.println(a + " * " + b + " = " + a.mul(b));
if (a.compareTo(b) >= 0) {
System.out.println(a + " / " + b + " = " + a.div(b));
}
}
}
final class BigInt implements Comparable<BigInt> {
int[] digits;
int size;
public BigInt() {
n = new int[1];
}
public BigInt(String s) {
n = new int[s.length()];
for (int i = 0; i < n.length; ++i) {
n[n.length - i - 1] = s.charAt(i) - '0';
}
n = trim(n);
}
private BigInt(int[] n) {
this.n = new int[n.length];
for (int i = 0; i < n.length; ++i) {
this.n[i] = n[i];
}
}
public BigInt add(BigInt o) {
return null;
}
public int compareTo(BigInt o) {
if (n.length < o.n.length) {
return -1;
}
else if (n.length > o.n.length) {
return +1;
}
for (int i = n.length-1; i >= 0; --i) {
if (n[i] < o.n[i]) {
return -1;
}
else if (n[i] > o.n[i]) {
return +1;
}
}
return 0;
}
public BigInt div(BigInt o) {
return null;
}
public boolean equals(Object o) {
if (o instanceof BigInt) {
if (n.length == ((BigInt)o).n.length) {
for (int i = 0; i < n.length; ++i) {
if (n[i] != ((BigInt)o).n[i]) {
return false;
}
}
return true;
}
}
return false;
}
public BigInt mul(BigInt o) {
int max = n.length > o.n.length ? n.length : o.n.length;
int[] newdigits = new int[n.length + o.n.length];
for (int i = 0; i < max; i++)
{
int carry = 0;
for (int i2 = 0; i2 < o.n.length || carry > 0; i2++)
{
int otherDigit = i2 >= o.n.length ? 0: o.n[i2];
int val = (n[i] * otherDigit) + carry;
newdigits[i + i2] += val % 10;
carry = val / 10;
}
}
return new BigInt(newdigits);
}
public BigInt sub(BigInt o) {
return null;
}
public String toString() {
String s = "";
for (int i : n) {
s = i + s;
}
return s;
}
private int[] trim(int[] nums) {
int size = nums.length;
for (int i = nums.length - 1; i > 0; --i) {
if (nums[i] != 0) {
break;
}
--size;
}
int[] res = new int[size];
for (int i = 0; i < size; ++i) {
res[i] = nums[i];
}
return res;
}
private int[] n;
}
Didn't feel like debugging your code, but here is how I'd implement that multiplication. It's a little less efficient, but easier to keep track of the carry.
public BigInt mul(BigInt o) {
int max = n.length > o.n.length ? n.length : o.n.length;
int[] newdigits = new int[n.length + o.n.length];
for (int i = 0; i < max; i++) {
for (int i2 = 0; i2 < max; i2++) {
int digit1 = i >= n.length ? 0 : n[i];
int digit2 = i2 >= o.n.length ? 0 : o.n[i2];
if (digit1 > 0 && digit2 > 0) {
int value = digit1 * digit2;
int pos = i + i2;
while (value > 0) {
int newDigit = (newdigits[pos] + value) % 10;
value = (newdigits[pos] + value) / 10;
newdigits[pos] = newDigit;
pos++;
}
}
}
}
return new BigInt(newdigits);
}
First, look the possible lengths:
[1] * [1] = [1] OR length(1) + length(1) -> length(1)
[9] * [9] = [8,1] OR length(1) + length(1) -> length(2)
One solution
Psudocode:
if (newdigits[ (length-1) ] == 0)
int[] newarray = new int[ (length-1) ]
copy newdigits to newarray
return newarray
You have to look at the carry of the largest digit before the earlier digits.
Secondly, you need to add the previous value you found to the val variable.
End of i=0:
[1, 9, 9, 7, 1, 0, 0, 0]
Adding during i=1:
[0, 1, 9, 9, 7, 1, 0, 0]
End of i=1:
[1, 10, 18, 16, 8, 1, 0, 0]
I suggest you try using Arrays.toString(newdigits) or use a debugger to catch these problems in the future.

Wagner Fischer algorithm + display steps

I made an implementation of Wagner Fischer algorithm in java with input cost, but I want to display all steps.
I search but can't find any idea.After a long time I tried to keep each transformation in matrix alongside cost and to go through back to first solution then reverse it... is this a good idea, if it is, how should I set condition?
kitten -> sitting
1.replace k with s
2.keep i
3.keep t
4.keep t
5.replace t
6.add g
I tried to make function for display steps and can't figure out how to solve it.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Principal {
static int c1, c2, c3;
static String word1, word2;
public static void main(String[] args) throws FileNotFoundException {
Scanner data_in = new Scanner(new File("data.in"));
word1 = data_in.next();
word2 = data_in.next();
c1 = data_in.nextInt();
c2 = data_in.nextInt();
c3 = data_in.nextInt();
System.out.printf("\nInsert: %s, Delete: %s, Replace: %s\n", c1, c2, c3);
System.out.printf("\nLevenstheinDistance: %s", LevenshteinDistance(word1, word2, c1, c2, c3));
}
private static int LevenshteinDistance(String str1, String str2, int InsCost, int DelCost, int ReplCost)
{
if(word1.length() == 0)
return InsCost*str1.length();
if(word2.length() == 0)
return DelCost*str2.length();
int substitutionCost = ReplCost;
if(ReplCost > InsCost + DelCost)
ReplCost = InsCost + DelCost;
Solution[][] ManageSol = new Solution[str1.length()+1][str2.length()+1];
for(int i = 0; i <= str1.length(); i++)
{
for(int j = 0; j <= str2.length(); j++){
ManageSol[i][j] = new Solution();
}
}
System.out.printf("\nLungime str1: %s", str1.length());
System.out.printf("\nLungime str2: %s", str2.length());
for(int i = 0; i <= str1.length(); i++)
{
for (int j = 0; j <= str2.length(); j++)
{
if (i == 0)
ManageSol[i][j].solution = j;
else if (j == 0)
ManageSol[i][j].solution = i;
else if (str1.charAt(i - 1) == str2.charAt(j - 1))
{
substitutionCost = 0;
ManageSol[i][j].ecqualTo(minimum(
ManageSol[i][j - 1].solution + InsCost,
ManageSol[i - 1][j].solution + DelCost,
ManageSol[i - 1][j - 1].solution + substitutionCost));
System.out.printf("\nManagerSol[%s, %s]: ch1: %s, ch2: %s", i, j, str1.charAt(i - 1), str2.charAt(j - 1));
}
else
{
substitutionCost = 1;
ManageSol[i][j].ecqualTo(minimum(
ManageSol[i][j - 1].solution + InsCost,
ManageSol[i - 1][j].solution + DelCost,
ManageSol[i - 1][j - 1].solution + substitutionCost));
System.out.printf("\nManagerSol[%s, %s]: ch1: %s, ch2: %s", i, j, str1.charAt(i - 1), str2.charAt(j - 1));
}
}
}
System.out.printf("\n");
path(ManageSol, str1.length(), str2.length(), str1, str2);
System.out.printf("\n");
for(int i = 0; i <= str1.length(); i++)
{
for (int j = 0; j <= str2.length(); j++)
{
System.out.printf("[%s,%s]:(%s,%s) ", i, j, ManageSol[i][j].solution, ManageSol[i][j].operation);
}
System.out.printf("\n");
}
return ManageSol[str1.length()][str2.length()].solution;
}
static int minimum(int x, int y)
{
if(x >= y)
return x;
return y;
}
static Solution minimum(int Ins, int Del, int Replace)
{
Solution solution = null;
if(Ins <= Del && Ins <= Replace)
{
solution = new Solution();
solution.operation = 1;
solution.solution = Ins;
return solution;
}
else if(Del <= Ins && Del <= Replace)
{
solution = new Solution();
solution.operation = 2;
solution.solution = Del;
return solution;
}
else
{
solution = new Solution();
solution.solution = Replace;
solution.operation = 0;
return solution;
}
}
//my failure, function that should display steps
static void path(Solution[][] ManagerSol, int i, int j, String str1, String str2)
{
if(ManagerSol[i][j].operation == 0)
{
System.out.printf("\nReplace %s -> %s", str1.charAt(i-1), str2.charAt(j-1));
if(i > 1 && j > 1)
path(ManagerSol, i-1,j-1, str1, str2);
}
if(ManagerSol[i][j].operation == 1)
{
System.out.printf("\nAdd %s on position %s", str2.charAt(j-1), i-1);
if(j > 1)
path(ManagerSol, i,j-1, str1, str2);
}
if(ManagerSol[i][j].operation == 2)
{
System.out.printf("\nDelete %s", str1.charAt(i-1));
if(j > 1)
path(ManagerSol, i-1,j, str1, str2);
}
}
}
Output for kitten to sitting:
[0,0]:(0,3) [0,1]:(1,3) [0,2]:(2,3) [0,3]:(3,3) [0,4]:(4,3) [0,5]:(5,3) [0,6]:(6,3) [0,7]:(7,3)
[1,0]:(1,3) [1,1]:(1,0) [1,2]:(2,1) [1,3]:(3,1) [1,4]:(4,1) [1,5]:(5,1) [1,6]:(6,1) [1,7]:(7,1)
[2,0]:(2,3) [2,1]:(2,2) [2,2]:(1,0) [2,3]:(2,1) [2,4]:(3,1) [2,5]:(4,1) [2,6]:(5,1) [2,7]:(6,1)
[3,0]:(3,3) [3,1]:(3,2) [3,2]:(2,2) [3,3]:(1,0) [3,4]:(2,1) [3,5]:(3,1) [3,6]:(4,1) [3,7]:(5,1)
[4,0]:(4,3) [4,1]:(4,2) [4,2]:(3,2) [4,3]:(2,2) [4,4]:(1,0) [4,5]:(2,1) [4,6]:(3,1) [4,7]:(4,1)
[5,0]:(5,3) [5,1]:(5,2) [5,2]:(4,2) [5,3]:(3,2) [5,4]:(2,2) [5,5]:(2,0) [5,6]:(3,1) [5,7]:(4,1)
[6,0]:(6,3) [6,1]:(6,2) [6,2]:(5,2) [6,3]:(4,2) [6,4]:(3,2) [6,5]:(3,2) [6,6]:(2,0) [6,7]:(3,1)
In general your idea is correct. It's even simpler than that. You don't need to store any additional information.
You can go backwards (starting from the end of the given strings) and use your dynamic programming values in the following way:
If one of the indices is 0, there is only one way to go.
Otherwise, you can look at 3 possible transitions "backwards" (from (i, j) to (i - 1, j - 1), (i - 1, j) and (i, j - 1)) and choose the one which yields the actual value for (i, j). If there are several possible options, you can choose any of them.
Once you know where to go from the given pair of positions, the operation is uniquely determined.
I'm not versed in Java but here is an illustration in JavaScript:
var a = 'kitten',
b = 'sitting';
var m = new Array(a.length + 1);
for (var i=0; i<m.length; i++){
m[i] = new Array(b.length + 1);
for (var j=0; j<m[i].length; j++){
if (i === 0) m[i][j] = j;
if (j === 0) m[i][j] = i;
}
}
for (var i=1; i<=a.length; i++){
for (var j=1; j<=b.length; j++){
// no change needed
if (a[i - 1] === b[j - 1]){
m[i][j] = m[i - 1][j - 1];
// choose deletion or insertion
} else {
m[i][j] = Math.min(m[i - 1][j], m[i][j - 1], m[i - 1][j - 1]) + 1;
}
}
}
console.log('a: ' + JSON.stringify(a));
console.log('b: ' + JSON.stringify(b));
var i = a.length,
j = b.length,
steps = '';
while (i !== 0 && j !== 0){
if (a[i - 1] === b[j - 1]){
steps = 'no change; ' + steps;
i--;
j--;
} else if (m[i - 1][j] < m[i][j - 1]){
steps = 'delete \'' + a[i - 1] + '\'; ' + steps;
i--;
} else if (m[i - 1][j] === m[i][j - 1]){
steps = 'replace \'' + a[i - 1] + '\' with \'' + b[j - 1] + '\'; ' + steps;
i--;
j--;
} else {
steps = 'insert \'' + b[j - 1] + '\'; ' + steps;
j--;
}
}
if (i === 0 && j > 0){
steps = 'insert first ' + j + ' elements from b; ' + steps;
} else if (j === 0 && i > 0){
steps = 'delete first ' + i + ' elements from a; ' + steps;
}
console.log('\n' + steps[0].toUpperCase() + steps.substr(1));
console.log('\nMatrix:\n');
for (var i in m){
console.log(JSON.stringify(m[i]));
}

problems trying to convert c sharp code into java

i'm try find most similar string in a array, and i found a code in c sharp that is this one
public static int LevenshteinDistance(string s, string t)
{
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
Console.WriteLine(cost);
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
return d[n, m];
}
and i'm trying to convert it into java but i get 1 error this is my code in java
public static int LevenshteinDistance(String s, String t)
{
int n = s.length();
int m = t.length();
int[][] d = new int[n + 1][ m + 1];
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (t[j - 1] == s[i - 1])? 0 : 1;
d[i][ j] = Math.min(
Math.min(d[i - 1][ j] + 1, d[i][ j - 1] + 1),
d[i - 1][ j - 1]+cost );
}
}
return d[n] [m];
}
i get the error in this line of code
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
the error that i have is "Array is required,but string found" this is what i have in my main
String []ray ={"food","drinks","stuffs"};
String fa="drink";
for (int i = 0; i < ray.length; i++)
{
System.out.print(LevenshteinDistance(fa, ray[i]));
}
i would appreciate any help
Use t.charAt(j-1) == s.charAt(i-1) as to access characters (letters) in string You cannot access them directly via index (brackets []).
int cost = (t.charAt(j - 1) == s.charAt(i - 1))? 0 : 1;
You are accessing the strings as arrays here with the [] array operator:
t[j - 1] == s[i - 1]
to get the nth char of a string, instead use .charAt(n)
so in this case change it to:
t.charAt(j - 1) == s.charAt(i - 1)
the same applies to the rest of the code.

Categories