第一次个人编程作业
| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/Class78-Grade2024-CS |
|---|---|
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/Class78-Grade2024-CS/homework/15702 |
| 这个作业的目标 | 设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。 |
项目仓库:https://github.com/dinnernumber1/3124004203/code1
学号:3124004203
开发语言:java
版本:v1.0
本程序采用基于字符二元组(Bigram)的召回率计算法来实现论文查重。相比于传统的中文分词(如结巴分词)或余弦相似度,该算法无需依赖外部词典,对短文本和局部增删改的检测更加灵敏,且时间和空间复杂度均为线性 O(n),执行效率极高。
一、开发耗时预估
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) |
|---|---|---|
| · Planning | · 计划 | 10 |
| · Estimate | · 估计这个任务需要多少时间 | 10 |
| · Development | · 开发 | 20 |
| · Analysis | · 需求分析 (包括学习新技术) | 20 |
| · Design Spec | · 生成设计文档 | 10 |
| · Design Review | · 设计复审 | 10 |
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 |
| · Design | · 具体设计 | 10 |
| · Coding | · 具体编码 | 10 |
| · Code Review | · 代码复审 | 10 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 10 |
| · Reporting | · 报告 | 20 |
| · Test Repor | · 测试报告 | 10 |
| · Size Measurement | · 计算工作量 | 10 |
| · Postmortem & Process Improvement Plan | · 事后总结,并提出过程改进计划 | 10 |
| · 合计 | 180 |
二、计算模块接口的设计与实现过程
1. 代码组织与类/函数设计
本项目的核心计算模块设计遵循“高内聚、低耦合”的原则,整体非常轻量级,仅包含一个核心类 Main。包含三个关键函数:
main(String[] args):程序的入口与协调者。负责接收命令行参数,通过 java.nio.file.Files 读取文件字节流,并调用核心计算函数,最后将结果格式化写入目标文件。
calcSimilarity(String orig, String copy):核心算法引擎。负责特征提取、哈希映射与重复率计算。
clean(String s):预处理辅助函数。负责过滤文本噪声,保留有效字符。
关系:main 函数处于顶层,它依次调用 clean 进行数据清洗,随后调用 calcSimilarity 计算重复率。三者形成一条清晰的数据流水线。
2. 关键函数流程图(文字描述)

3. 算法关键与独到之处
不依赖词典的 Bigram 滑动窗口:抛弃了传统分词工具(如结巴分词),采用字符二元组(Bigram)切分。这能更好地捕捉文本的局部词序特征,对短文本和局部增删改的查重极为敏感。
位运算极速特征压缩(独到之处):在处理 Bigram 时,没有使用 String.substring(i, i+2),因为这会引发大量小字符串对象的创建,导致极高的 GC(垃圾回收)压力。代码创造性地使用了 (orig.charAt(i) << 16) | orig.charAt(i + 1),将两个字符无损压缩为一个 int 整数。这不仅将哈希查找的复杂度降到了 O(1),更极大降低了内存开销。
召回率(Recall)度量:重复率公式采用 抄袭版命中的Bigram数 / 抄袭版总Bigram数,这比余弦相似度更能准确反映“抄袭版中有多少内容来源于原文”。
三、 计算模块接口部分的性能改进
1. 改进花费的时间与思路
初版思路(耗时约30分钟):最初采用 List
性能瓶颈:在处理较大文本时,频繁的字符串截取和对象创建导致 JVM 内存频繁 GC,耗时急剧上升。
改进方案(耗时约1小时):将 String 替换为位运算打包的 int,存储在 HashSet
2. 性能分析图与最大消耗函数

最大的消耗函数是Main方法
四、 计算模块部分单元测试展示
采用一般的测试方法,可以大概直到程序有没有问题
public class MainTest {
public static void main(String[] args) {
// 1. 测试 clean()
String raw = "A B C , 1-2-3 你好!\n这是一个测试文本。";
String expected = "ABC123你好这是一个测试文本";
if (!expected.equals(Main.clean(raw))) {
System.err.println("clean() 测试失败!");
} else {
System.out.println("clean() 测试通过");
}
// 2. 测试 calcSimilarity()
String orig = "今天是星期天,天气晴,今天晚上我要去看电影。";
String copy = "今天是周天,天气晴朗,我晚上要去看电影。";
double rate = Main.calcSimilarity(orig, copy);
System.out.println("局部修改相似度: " + rate); // 预期 0.3 ~ 0.8 之间
}
}

五、 计算模块部分异常处理说明
在程序设计中,异常处理旨在保证程序不会“异常退出”(扣分项),并占用尽可能少的内存。
1. 异常设计目标与场景
目标:防止非法路径、文件缺失、参数不足导致的崩溃,保障系统在压力下稳定运行。
场景:命令行参数不足、文件路径不存在、用户没有文件读取权限、文件编码不是 UTF-8。
2. 单元测试样例与错误场景
异常一:命令行参数不足
场景:用户在控制台输入 java -jar main.jar,未提供3个必需的参数。
防御代码/测试:在 main 方法首行判断 args.length < 3,主动打印用法提示并 System.exit(1)。
异常二:文件不存在或读取失败(IOException)
场景:路径写错、文件被其他程序占用,或文件不存在。
防御代码/测试:
@Test
public void testReadFileException() {
// 构造错误路径
String[] args = {"non_existent.txt", "copy.txt", "ans.txt"};
// 使用 try-catch 捕获异常,确保程序优雅退出(实际测试通过 Main.main(args) 调用)
try {
Main.main(args);
fail("应当捕获 IOException 并退出");
} catch (Exception e) {
// 捕获并验证
assertTrue(e instanceof java.io.IOException || e instanceof java.lang.SecurityException);
}
}
改进后:在 main 方法中,将 Files.readAllBytes 和 Files.write 包裹在 try-catch (IOException e) 中。若发生异常,使用 System.err 打印错误信息,并调用 System.exit(1) 标准退出,确保评测系统能获取到非零退出码并判断为程序异常终止,而不是打印一堆 Java 堆栈显得程序崩溃且超时。
六、开发实际耗时
| PSP2.1 | Personal Software Process Stages | 实际耗时(分钟) |
|---|---|---|
| · Planning | · 计划 | 10 |
| · Estimate | · 估计这个任务需要多少时间 | 10 |
| · Development | · 开发 | 30 |
| · Analysis | · 需求分析 (包括学习新技术) | 20 |
| · Design Spec | · 生成设计文档 | 20 |
| · Design Review | · 设计复审 | 10 |
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 |
| · Design | · 具体设计 | 10 |
| · Coding | · 具体编码 | 10 |
| · Code Review | · 代码复审 | 10 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 10 |
| · Reporting | · 报告 | 30 |
| · Test Repor | · 测试报告 | 10 |
| · Size Measurement | · 计算工作量 | 10 |
| · Postmortem & Process Improvement Plan | · 事后总结,并提出过程改进计划 | 20 |
| · 合计 | 220 |
浙公网安备 33010602011771号