C ++最长公共子序列实现错误O(n * m)

时间:2016-07-11 15:30:14

标签: c++ arrays algorithm dynamic-programming subsequence

我正在浏览一些关于geeksforgeeks的动态编程文章,并遇到了最长公共子序列问题。我没有想出自己的指数天真解决方案的实现,但是在解决了纸上问题的一些例子后,我提出了我认为成功实现O(n*m)版本的内容。然而,OJ证明我错了。我的算法失败了输入字符串:

  • "LRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJYBLDBEFSARCBYNECDYGGXXPKLORELLNMPAPQFWKHOPKMCO"
  • "QHNWNKUEWHSQMGBBUQCLJJIVSWMDKQTBXIXMVTRRBLJPTNSNFWZQFJMAFADRRWSOFSBCNUVQHFFBSAQXWPQCAC"

我对算法的思考过程如下。我想维护一个DP数组,其长度是字符串a的长度,其中a是输入字符串中较小的一个。 dpA[i]将是以a[i]结尾的最长公共子序列。为此,我需要遍历索引a中的字符串0 => length-1并查看a[i]中是否存在b。如果a[i]中存在b,则它将位于pos位置。

  1. 如果dp[i]1
  2. ,请先将dp[i]标记为0
  3. 要知道a[i]是现有子序列的扩展,我们必须经过a并找到i后面的第一个与b后面的值相匹配的字符{ {1}}。我们分别调用这些匹配值posj的索引。由于我们已涵盖所有k且已填写a[0...i-1],因此我们保证此值已成为我们之前看到的值。当我们找到第一个匹配项dpA[0...i-1]时,因为我们正在扩展以dpA[i] = dpA[j]+1结尾的前一个子序列。冲洗重复。
  4. 显然这种方法并不完美,或者我不会问这个问题,但我似乎无法看到算法的问题。我已经看了很长时间,我几乎不能再考虑它,但任何关于如何修复它的想法都将不胜感激!

    a[j]

    修改

    我认为复杂性实际上可能是int longestCommonSubsequenceString(const string& x, const string& y) { string a = (x.length() < y.length()) ? x : y; string b = (x.length() >= y.length()) ? x : y; vector<int> dpA(a.length(), 0); int pos; bool breakFlag = false; for (int i = 0; i < a.length(); ++i) { pos = b.find_last_of(a[i]); if (pos != string::npos) { if (!dpA[i]) dpA[i] = 1; for (int j = i-1; j >= 0; --j) { for (int k = pos-1; k >= 0; --k) { if (a[j] == b[k]) { dpA[i] = dpA[j]+1; breakFlag = true; break; } if (breakFlag) break; } } } breakFlag = false; } return *max_element(dpA.begin(), dpA.end()); }

0 个答案:

没有答案