The code i wrote a while ago recently caused a disaster and as I reviewed it I found it is the silliest code I've ever written,

 static int BadMaximalMatch(TListRef list1, int start1, int count1, TListRef list2, int start2, int count2,
const IEqualityComparer<T> &comparer, List<int> &indices1, List<int> &indices2)
{
if (count1 <= || count2 <= )
{
return ;
} bool eq = comparer.Equals(list1[start1], list2[start2]);
if (eq)
{
indices1.Add(start1);
indices2.Add(start2); return BadMaximalMatch(list1, start1+, count1-, list2, start2+, count2-, comparer, indices1, indices2) + ;
}
else
{
bool eq01 = count2 >= && comparer.Equals(list1[start1], list2[start2+]);
bool eq10 = count1 >= && comparer.Equals(list1[start1+], list2[start2]); int crossDiff;
if (eq01 && eq10)
{
crossDiff = ;
}
else if (eq01 && !eq10)
{
return BadMaximalMatch(list1, start1, count1, list2, start2+, count2-, comparer, indices1, indices2);
}
else if (!eq01 && eq10)
{
return BadMaximalMatch(list1, start1+, count1-, list2, start2, count2, comparer, indices1, indices2);
}
else
{
bool eq11 = count1 >= && count2 >= && comparer.Equals(list1[start1+], list2[start2+]);
if (eq11)
{
indices1.Add(start1+);
indices2.Add(start2+);
return BadMaximalMatch(list1, start1+, count1-, list2, start2+, count2-, comparer, indices1, indices2)+;
}
crossDiff = ;
} List<int> temp11, temp12, temp21, temp22;
int m1 = , m2 = ;
if (count1 < count2)
{
// calculate m1 first, as maximum of m1 is greater than that of m2
// maximum: min(count1, count2-crossDiff)
m1 = BadMaximalMatch(list1, start1, count1, list2, start2+crossDiff, count2-crossDiff, comparer, temp11, temp12);
if (m1 < count1 && m1 < count2-crossDiff)
{
// m1 hasn't reached its maximum possible value
// maximum: min(count1-crossDiff, count2)
m2 = BadMaximalMatch(list1, start1+crossDiff, count1-crossDiff, list2, start2, count2, comparer, temp21, temp22);
}
}
else
{
// calculate m2 first, as maximum of m2 is greater than that of m1
m2 = BadMaximalMatch(list1, start1+crossDiff, count1-crossDiff, list2, start2, count2, comparer, temp21, temp22);
if (m2 < count2 && m2 < count1-crossDiff)
{
// m2 hasn't reached its maximum possible value
// maximum: min(count1, count2-crossDiff)
m1 = BadMaximalMatch(list1, start1, count1, list2, start2+crossDiff, count2-crossDiff, comparer, temp11, temp12);
}
} if (m2 > m1)
{
for (int i = ; i < m2; i++)
{
indices1.Add(temp21[i]);
indices2.Add(temp22[i]);
}
return m2;
}
else
{
for (int i = ; i < m1; i++)
{
indices1.Add(temp11[i]);
indices2.Add(temp12[i]);
}
return m1;
}
}
}

It simply finds out the maximum common sublist of two. And I was dumb enough to not realize it was a very simple problem and be spending quite a while on a complex recursive algorithm as above to solve that. So far there's no evidence it's buggy, but it's as bad as buggy when dealing with just more than 20 data points. A random test today showed that the code above is problematic in that it doesn't take into account some of the possible options that goes across the one that it believes is optimal. Basically the algorithm should only step forward when the current item from either list has no match in the other. So the correct one should be

 static int MaximalSublistMatch_Slow(TListRef list1, int start1, int count1, TListRef list2, int start2, int count2,
const IEqualityComparer<T> &comparer, List<int> &indices1, List<int> &indices2)
{
if (count1 <= || count2 <= )
{
return ;
} bool eq = comparer.Equals(list1[start1], list2[start2]);
if (eq)
{
indices1.Add(start1);
indices2.Add(start2); return MaximalSublistMatch_Slow(list1, start1 + , count1 - , list2, start2 + , count2 - , comparer, indices1, indices2) + ;
}
else
{
const T &v1 = list1[start1];
const T &v2 = list2[start2]; int l1Match=-, l2Match=-;
for (int i = start2 + ; i < start2+count2; i++)
{
if (list2[i] == v1)
{
l1Match = i;
break;
}
} for (int i = start1 + ; i < start1+count1; i++)
{
if (list1[i] == v2)
{
l2Match = i;
break;
}
} if (l1Match < && l2Match < )
{
return MaximalSublistMatch_Slow(list1, start1 + , count1 - , list2, start2 + , count2 - , comparer, indices1, indices2);
}
else
{
// try both
List<int> temp11, temp12, temp21, temp22;
int r2 = ;
int r1 = MaximalSublistMatch_Slow(list1, start1, count1, list2, start2 + , count2 - , comparer, temp11, temp12);
if (r1 < std::min(count1 - , count2))
{
r2 = MaximalSublistMatch_Slow(list1, start1 + , count1 - , list2, start2, count2, comparer, temp21, temp22);
}
if (r1 < r2)
{
for (int i = ; i < r2; i++)
{
indices1.Add(temp21[i]);
indices2.Add(temp22[i]);
}
return r2;
}
else
{
for (int i = ; i < r1; i++)
{
indices1.Add(temp11[i]);
indices2.Add(temp12[i]);
}
return r1;
}
}
}
}

A simpler version naive alternative (not equivalent, but ok for most use; and minor change to it can improve accuracy not so sure of what significance this method can be, with a fast optimum approach found available) is

It's equivalent is,

 // this is a version of maximal match with a complexity of O(N)
static int MaximalMatch(TListRef list1, int start1, int count1, TListRef list2, int start2, int count2,
const IEqualityComparer<T> &comparer, List<int> &indices1, List<int> &indices2)
{
int matchStart2 = start2;
for (int i1 = start1; i1 < start1 + count1; i1++)
{
const T &v1 = list1[i1];
for (int i2 = matchStart2; i2 < start2 + count2; i2++)
{
const T &v2 = list2[i2];
if (comparer.Equals(v1,v2))
{
indices1.Add(i1);
indices2.Add(i2);
matchStart2 = i2+;
break;
}
}
}
return indices1.GetCount();
}

Of course this is is epically faster, simpler and less error-prone than the previous one. but it doesn't provide the optimal result.
You can imagine how an application would suffer from the exp(N)-complexity shit.

The fast equivalent should be using dynamic programming and go as follows

(The standard C# version has been updated to the QSharp library at https://qsharp.codeplex.com/SourceControl/latest#QSharp/QSharp.Scheme.Classical.Sequential/MaxSublistMatch.cs)

 struct MaxMatchDPResult
{
bool Done;
List<int> Indices1;
List<int> Indices2;
}; // FB: 6462
// NOTE this is a version of maximal match using dynamic programming
// it has a time complexity of around O(N*N) and space complexity of about O(N^4)
// This is a recommended version as it provides optimal result and is fast
static int MaximalSublistMatch_DP(TListRef list1, int start1, int count1, TListRef list2, int start2, int count2,
const IEqualityComparer<T> &comparer, List<int> &indices1, List<int> &indices2)
{
int maxSofar = ;
std::vector<std::vector<MaxMatchDPResult>> map;
for (int i = ; i < count1+; i++)
{
map.push_back(std::vector<MaxMatchDPResult>());
for (int j = ; j < count2+; j++)
{
map[i].push_back(MaxMatchDPResult());
map[i][j].Done = false;
}
}
return MaximalSublistMatch_DP(list1, start1, count1, list2, start2, count2, comparer, indices1, indices2, map);
} static int MaximalSublistMatch_DP_Lookup(TListRef list1, int start1, int count1, TListRef list2, int start2, int count2,
const IEqualityComparer<T> &comparer, List<int> &indices1, List<int> &indices2, std::vector <std::vector<MaxMatchDPResult>> &map)
{
if (count1 <= || count2 <= )
{
return ;
}
const MaxMatchDPResult &result = map[count1][count2];
int r;
if (result.Done)
{
r = result.Indices1.GetCount();
for (int i = ; i < r; i++)
{
indices1.Add(result.Indices1[i]);
indices2.Add(result.Indices2[i]);
}
}
else
{
List<int> tempIndices1, tempIndices2;
r = MaximalSublistMatch_DP(list1, start1, count1, list2, start2, count2, comparer, tempIndices1, tempIndices2, map);
map[count1][count2].Done = true;
map[count1][count2].Indices1 = tempIndices1;
map[count1][count2].Indices2 = tempIndices2;
for (int i = ; i < r; i++)
{
indices1.Add(tempIndices1[i]);
indices2.Add(tempIndices2[i]);
}
}
return r;
} static int MaximalSublistMatch_DP(TListRef list1, int start1, int count1, TListRef list2, int start2, int count2,
const IEqualityComparer<T> &comparer, List<int> &indices1, List<int> &indices2, std::vector<std::vector<MaxMatchDPResult>> &map)
{
bool eq = comparer.Equals(list1[start1], list2[start2]);
if (eq)
{
indices1.Add(start1);
indices2.Add(start2);
int r = MaximalSublistMatch_DP_Lookup(list1, start1 + , count1 - , list2, start2 + , count2 - , comparer, indices1, indices2, map) + ;
return r;
} List<int> temp11, temp12, temp21, temp22;
int r2 = ;
int r1 = MaximalSublistMatch_DP_Lookup(list1, start1, count1, list2, start2 + , count2 - , comparer, temp11, temp12, map);
if (r1 <
#if defined(min)
min(count1 - , count2)
#else
std::min(count1 - , count2)
#endif
)
{
r2 = MaximalSublistMatch_DP_Lookup(list1, start1 + , count1 - , list2, start2, count2, comparer, temp21, temp22, map);
}
if (r2 > r1)
{
for (int i = ; i < r2; i++)
{
indices1.Add(temp21[i]);
indices2.Add(temp22[i]);
}
return r2;
}
else
{
for (int i = ; i < r1; i++)
{
indices1.Add(temp11[i]);
indices2.Add(temp12[i]);
}
return r1;
}
}

This was stupid, but classic!

Darkest page of my coding life的更多相关文章

  1. 芝麻HTTP:Python爬虫实战之抓取爱问知识人问题并保存至数据库

    本次为大家带来的是抓取爱问知识人的问题并将问题和答案保存到数据库的方法,涉及的内容包括: Urllib的用法及异常处理 Beautiful Soup的简单应用 MySQLdb的基础用法 正则表达式的简 ...

  2. 全栈开发工程师微信小程序-中(下)

    全栈开发工程师微信小程序-中(下) 微信小程序视图层 wxml用于描述页面的结构,wxss用于描述页面的样式,组件用于视图的基本组成单元. // 绑定数据 index.wxml <view> ...

  3. 简单python爬虫案例(爬取慕课网全部实战课程信息)

    技术选型 下载器是Requests 解析使用的是正则表达式 效果图: 准备好各个包 # -*- coding: utf-8 -*- import requests #第三方下载器 import re ...

  4. python练习册 每天一个小程序 第0000题

    PIL库学习链接:http://blog.csdn.net/column/details/pythonpil.html?&page=1 1 #-*-coding:utf-8-*- 2 __au ...

  5. Selenium的PO模式(Page Object Model)[python版]

     Page Object Model 简称POM  普通的测试用例代码: .... #测试用例 def test_login_mail(self): driver = self.driver driv ...

  6. 使用page object模式抓取几个主要城市的pm2.5并从小到大排序后写入txt文档

    #coding=utf-8from time import sleepimport unittestfrom selenium import webdriverfrom selenium.webdri ...

  7. 使用webstom或者idea上传代码到github或coding

    鉴于github网络速度太慢,建议用coding.先介绍github上传方式,因为webstom或idea集成了github,方法简单. git是一个版本控制器,他的作用是管理代码.比如你修改了代码, ...

  8. Selenium的PO模式(Page Object Model)|(Selenium Webdriver For Python)

            研究Selenium + python 自动化测试有近两个月了,不能说非常熟练,起码对selenium自动化的执行有了深入的认识. 从最初无结构的代码,到类的使用,方法封装,从原始函数 ...

  9. Coding源码学习第二部分(FunctionIntroManager.m)

    接上篇.上篇有一个细节忘了写,在Coding_iOS-Info.plist 里面添加了一个key 是 Status bar is initially hidden  Value 是 YES,在appl ...

随机推荐

  1. ISD1700系列多段语音录放系列

    ISD1700系列语音芯片的基础指示:

  2. 谈谈我的编程之路---WAMP(四)

    WAMP的一些配置与使用心得(windows)W-windows,说到windows,其实大家都最熟悉不过了,GUI(graphic user interface)图形界面就没有什么可说的了,基本会用 ...

  3. Visual Studio 推荐插件--高量,变量高量,语法高亮

    1  WordLight for 2008 下载网址:http://visualstudiogallery.msdn.microsoft.com/ad686131-47d4-4c13-ada2-5b1 ...

  4. MYSQL的增删改查语句样码

    慢慢来,慢慢来.. 增: INSERT INTO person (person_id, fname, lname, gender, birth_date) VALUES (null, 'William ...

  5. C# 重绘tabControl,添加关闭按钮(续)

    在上一篇随笔中,添加关闭按钮是可以实现 ,但细心一点就会发现,每次关闭一个选项卡,tableControl都会自动跳到第一个页面,显然 这不是我们想要的,为此,我修改了部分的代码.除此之外,我还添加了 ...

  6. 面试题之【打印1到最大的N位数】

    题目描述:给定一个数字N,打印从1到最大的N位数. 看起来像是很简单的问题(虽然实际也不是很难...)我们很容易写出这样的代码: #include<iostream> #include&l ...

  7. Ubuntu14.04LTS系统QQ的安装:pidgin-lwqq

    本人是轻度聊天工具使用者(大言不惭是轻度,偷笑),发现输入法到博主也有解决linux下QQ的解决方法,一并抄过来,有需要,请联系原作者 参考链接:http://www.cnblogs.com/zhj5 ...

  8. C#中var和dynamic

    var与dynamic这两个关键字,只是看起来很相似,仅此而已!var表示“变量的类型是在编译时决定的”,但是dynamic表 示“变量的类型是在运行时决定的”.因此,dynamic与var具有截然不 ...

  9. loj 1377 (bfs)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1377 思路:这道题只要处理好遇到"*"这种情况就可以搞定了.我们可 ...

  10. C++异常处理机制几种方法

    一.异常 迄今为止,我们处理程序中的错误一般都是用if语句测试某个表达式,然后处理错误的特定义代码. C++异常机制使用了三个新的关键字  (SEH(结构化异常处理)) try    ──标识可能出现 ...