You could argue that what dynamic programming does isn't even really memoization in the sense that it's used in the Lisp/FP world.
Dynamic programming algorithms usually work from the bottom-up: you fill a table with the first stage of the algorithm, and then compute subsequent stages until you've converged on a solution. Memoization almost always works from the top-down: you start with a naive recursive algorithm, and then store function call results in a hashtable or other data structure to avoid recomputing them.
They both involve avoiding recomputation by storing intermediate results in memory. But saying that this makes them the same is sorta like saying that recursion and iteration are the same because they both use the program counter.
Recursion with a tail call and iteration are the same, though. The difference between tail recursion and iteration is whether or not the target of a jump happens to be the start of a function or not.
They're the same in terms of what the machine is doing, assuming your compiler does tail-call optimization. That's not the same as being "the same" - they present a very different abstraction to the programmer. That was the point of my analogy.
You can see this difference by looking at one of the ways this abstraction leaks. Consider stack traces. In a sane language, you expect an error to give you a stack trace of functions that have been called. If you treat recursion as iteration, then either you'll have to omit some function calls from the stack, or your algorithm won't work in constant space anymore. Either violates some expectations of the programmer.
I also said "recursion" and not "tail recursion". There are some algorithms that are impossible to implement without an external stack under iteration (eg. tree traversal), and others where you need to use iteration because a stack is not appropriate (eg. breadth-first search).
Dynamic programming algorithms usually work from the bottom-up: you fill a table with the first stage of the algorithm, and then compute subsequent stages until you've converged on a solution. Memoization almost always works from the top-down: you start with a naive recursive algorithm, and then store function call results in a hashtable or other data structure to avoid recomputing them.
They both involve avoiding recomputation by storing intermediate results in memory. But saying that this makes them the same is sorta like saying that recursion and iteration are the same because they both use the program counter.