github仓库链接:3123004747/cheaker at main · lwy8852/3123004747
Psp表格
psp阶段 | 预估耗时 | 实际耗时 |
---|---|---|
· 计划 (Planning) | 15 | 15 |
· 估计任务时间 (Estimate) | 40 | 55 |
· 开发 (Development) | 200 | 220 |
· 需求分析 (Analysis) | 30 | 25 |
· 生成设计文档 (Design Spec) | 20 | 20 |
· 设计复审 (Design Review) | 25 | 30 |
· 代码规范 (Coding Standard) | 20 | 25 |
· 具体设计 (Design) | 20 | 20 |
· 具体编码 (Coding) | 15 | 20 |
· 代码复审 (Code Review) | 10 | 15 |
· 测试(包括修改) (Test) | 30 | 25 |
· 报告 (Reporting) | 60 | 50 |
· 测试报告 (Test Report) | 20 | 30 |
· 计算工作量 (Size Measurement | 40 | 50 |
事后总结与改进 (Postmortem) | 30 | 50 |
· 总计 (Total) | 575 | 650 |
1. 模块接口设计与实现
流程图
核心模块
-
文件读取模块
java
public static String readFile(String path) throws IOException {return new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8); }
-
文本预处理模块
java
private static final Pattern PATTERN = Pattern.compile("[\\p{P}\\s]"); public static String preprocess(String text) {return PATTERN.matcher(text).replaceAll("").toLowerCase(); }
-
相似度计算模块
java
public static double calculateSimilarity(String text1, String text2) {int[][] counts = new int[2][65536];for (char c : text1.toCharArray()) counts[0][c]++;for (char c : text2.toCharArray()) counts[1][c]++;double dotProduct = 0.0, norm1 = 0.0, norm2 = 0.0;for (int i = 0; i < 65536; i++) {dotProduct += counts[0][i] * counts[1][i];norm1 += counts[0][i] * counts[0][i];norm2 += counts[1][i] * counts[1][i];}return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2)); }
-
结果输出模块
java
public static void writeResult(String path, double similarity) throws IOException {Files.write(Paths.get(path), String.format("%.2f", similarity).getBytes(StandardCharsets.UTF_8)); }
2. 性能改进
性能分析
改进点
-
字符统计优化
- 使用
int[256]
代替int[65536]
,仅统计 ASCII 字符。
java
for (char c : text1.toCharArray()) {if (c < 256) counts[0][c]++; }
- 使用
-
正则表达式预编译
- 正则表达式已预编译为静态常量。
java
private static final Pattern PATTERN = Pattern.compile("[\\p{P}\\s]");
-
并行化处理
- 对超大文本使用并行流。
java
text1.chars().parallel().forEach(c -> counts[0][c]++);
3. 单元测试展示
测试用例
-
完全相同的文本
@Test public void testIdenticalTexts() {String text = "Hello world!";double result = Main.calculateSimilarity(text, text);assertEquals(1.00, result, 0.001); }
-
完全不同的文本
@Test public void testDifferentTexts() {String original = "abcdef";String plagiarized = "ghijkl";double result = Main.calculateSimilarity(original, plagiarized);assertEquals(0.0, result, 0.001); }
-
空文本
@Test public void testEmptyText() {String original = "";String plagiarized = "Hello world!";double result = Main.calculateSimilarity(original, plagiarized);assertEquals(0.0, result, 0.001); }
4. 异常处理说明
异常类型
-
文件不存在
try {String content = readFile("nonexistent.txt"); } catch (IOException e) {System.err.println("文件不存在!"); }
-
空文本
if (text1.isEmpty() || text2.isEmpty()) {return 0.0; }
-
命令行参数错误
if (args.length != 3) {System.err.println("用法: java -jar main.jar 原文文件 抄袭文件 输出文件");System.exit(1); }