内容介绍
- 基本功能实现
a) 预处理
b) LCS实现
c) 给出合适的r,求出D(i,j) - 解决变量名代换的问题
a) 字面距离
b) 正则化截取
实验概述
- 对待查重的文件的预处理
- LCS基本实现
- 对r、D(i,j)和递归公式的推导
- 字面距离(Levenshtein距离和Jaro-Winkler距离)
- 正则化表达式截取字符串
实验内容
-
基本实现
a) 预处理
首先,考虑到不同人编程的习惯差异,会产生不同的缩进,因此空格、回车的数目是因人而异的,需要在查重前对代码使用clang format进行格式化,消除这些差异,并将注释语句删掉。而针对不同的语言,对于括弧“{}”的使用习惯也不同,如C、C++中,括弧的习惯是:
void Func()
{
…
}
而在java和一些语言中更适用于这种写法:
void Func(){
…
}
因此括弧会影响查重,可以用方法将其去除或者在对比时无视,消除差异。
其次,匹配规则是,当S1与S2字符串进行匹配后,S2不再与其他字符串进行匹配。如下图,当A.cpp中有字符串与B.cpp的字符串匹配成功后,将B.cpp的字符串对应的行标记,此后便不与之匹配。
b) LCS实现
LCS的基本实现思想是,取两个字符串的字符一一比对,若两者相同则令S[i][j] = S[i][j] + 1,否则S[i][j] = max(S[i-1][j], S[i][j-1]),这也是符合LCS的推导公式的。而得到最长相同子串的方法是通过数据结构的栈实现的,因为一般的实现会记录字符的方向,而输出字符串是要从S矩阵的右下角逆序输出