341-a3-q1.tex 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. \documentclass[a4paper]{article}
  2. %% Language and font encodings
  3. \usepackage[english]{babel}
  4. \usepackage[utf8x]{inputenc}
  5. \usepackage[T1]{fontenc}
  6. %% Sets page size and margins
  7. \usepackage[a4paper,top=2cm,bottom=2cm,left=2cm,right=2cm,marginparwidth=1.75cm]{geometry}
  8. %% Useful packages
  9. \usepackage{amsmath}
  10. \usepackage{graphicx}
  11. \usepackage[colorinlistoftodos]{todonotes}
  12. \usepackage[colorlinks=true, allcolors=blue]{hyperref}
  13. \title{CS 341 A3 Q1}
  14. \author{Tareef Dedhar - 20621325}
  15. \begin{document}
  16. \maketitle
  17. \section{LCS of N Strings}
  18. \subsection{Description/Correctness}
  19. For each string we will keep track of our "current position" as an element of the array positions. This is initialized with the max length of each string as the value for its index. Then, we call LCS on this array. If the character at the position is equal for all strings, we add 1 to the solution, decrement all indices, and recurse. If not, then we take the max of each possible sub-problem where these are recursing while decrementing only one position (so n recursive calls). This solution can and should use caching of calculated values, of course (this can be implemented as an n-dimensional array, where each possible LCS value for each state of positions[] is stored once calculated). This algorithm considers all options, as if all strings end with the same value that must be part of the subsequence, and if not, this considers the subproblem for each string as being the one to decrement, and follows the same logic in each recursive call, effectively checking every possible combination of strings.
  20. \subsection{Pseudocode}
  21. \begin{verbatim}
  22. for strings 0 thru n:
  23. int positions[n] = length of each string at the given index
  24. LCS(int positions[]):
  25. if (s0[positions[0]] == s1[positions[1]] == ... == sn[positions[n]]):
  26. for each i in positions:
  27. positions[i] -= 1
  28. return 1 + LCS(positions)
  29. else:
  30. int temp[n]
  31. for each i in temp:
  32. temp_positions = positions
  33. temp_positions[i] -= 1
  34. temp[i] = LCS(temp_positions)
  35. return Max(temp)
  36. \end{verbatim}
  37. \subsection{Time Complexity}
  38. The time complexity of this algorithm is as follows:
  39. Generating the inital array of positions, assuming length is a known quantity of each string, takes $\Theta$(n) time (where n is the amount of strings). From there, we consider the initial call to the recursive function. We first iterate through the array, checking for equality. This takes $\Theta$(n) time. If this check is true, we recurse on the same set of strings with 1 less character. However, this is the best case. In the worst case, we perform this same calculation and check, but recurse n times, with only 1 out of the n strings being decremented. If there is no common subsequence, then this means we have n calls which run n calls themelves, which means we have a runtime of O($n^n$).
  40. \end{document}