软件工程第二次作业

软件工程第二次作业

github链接 https://github.com/pigyoung661/pigyoung661/tree/main/3123004235
这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class34Grade23ComputerScience/homework/13477
这个作业的目标 设计一个论文查重程序,并进行性能分析与测试

一,PSP表

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 40 50
· Estimate · 估计这个任务需要多少时间 30 50
Development 开发 200 320
· Analysis · 需求分析(包括学习新技术) 100 90
· Design Spec · 生成设计文档 30 40
· Design Review · 设计复审 30 40
· Coding Standard · 代码规范(为目前的开发制定合适的规范) 20 20
· Design · 具体设计 40 60
· Coding · 具体编码 60 90
· Code Review · 代码复审 30 20
· Test · 测试(自我测试,修改测试,提交修改) 40 40
Reporting 报告 50 70
· Test Report · 测试报告 30 50
· Size Measurement · 计算工作量 20 25
· Postmortem & Process improvement Plan · 事后总结,并提出修改过程改进计划 20 20
合计 740 985

二,计算机模块接口的设计和实现过程

类函数构成:

  1. SimilarityCalculator.java(核心计算类)
    • 核心函数:
      • calculateSimilarity():总入口,协调各模块计算最终相似度
      • calculateSentenceSimilarity():句子级匹配主逻辑
      • calculateTwoSentencesSimilarity():单个句子对的相似度计算
      • normalizeWords():同义词标准化处理
      • calculateLCSLength():最长公共子序列计算
      • calculateWordFrequencySimilarity():词频辅助验证
  2. TextProcessor.java(文本处理工具类)
    • 核心函数:
      • cleanText():文本清洗(去干扰字符、标点标准化)
      • splitIntoSentences():按标点分割句子
      • segmentSentence():句子分词(按字 / 词分割)
      • getSynonymMap():提供同义词映射表
      • getNoiseChars():提供干扰字符集合
  3. FileProcessor.java(文件操作类)
    • 核心函数:
      • readFile():读取文件内容(UTF-8 编码)
      • writeFile():写入结果到文件
  4. Main.java(程序入口类)
    • 核心函数:
      • main():解析命令行参数,调用各模块完成流程

(1)具体运行流程图

微信图片_20250923153257_20_134

(2)算法逻辑与总体设计

核心逻辑:采用 “句子级匹配为主、词频分析为辅” 的双层加权策略(句子相似度占 80%,词频相似度占 20%),既捕捉局部句子结构的相似性,又兼顾整体文本的词汇分布特征。

  • 避免纯词频或纯哈希的局限性,同时适配 “整句抄袭修改” 和 “大段内容搬运” 等多种抄袭模式。

  • 同义词动态映射:通过预设同义词库对文本进行标准化处理,将表层表述差异转化为统一语义特征,解决 “换词不换义” 的抄袭识别问题。

  • 最长公共子序列(LCS)算法:针对句子内部结构,通过计算最长公共子序列长度与句子总长度的比值,量化句子结构的相似性,有效识别 “语序不变、局部修改” 的抄袭模式。

  • 定向噪声过滤:通过预设干扰字符集合,精准移除无意义干扰项(如随机插入的特殊字符、冗余符号),还原文本核心内容,避免噪声对匹配结果的干扰。

  • 全流程标准化:包含标点统一(全角 / 半角转换)、大小写归一化、停用词过滤等预处理步骤,确保不同格式的文本在同一基准上进行比对。

  • 职责单一的类设计:将文件操作、文本预处理、核心计算分离为独立模块,降低耦合度,便于单独优化某一环节(如扩展同义词库、替换分词算法)。

  • 阈值可调的判断逻辑:句子匹配阈值(默认 60%)、权重分配比例等参数可根据场景灵活调整,兼顾严格和宽松的查重需求。

三,计算模块接口的性能改进

1,耗时统计

句子级匹配粒度设计 30 以句子为单位而非字符级比对
文本清洗前置处理 20 cleanText先过滤干扰再进入计算
算法逻辑分层实现 40 拆分句子匹配与词频计算为独立方法
边界条件提前判断 15 空文本直接返回 0.0

2,优化思路

  1. 采用句子级比对而非字符级或文档级,既避免了字符级比对的低效(O (n²) 复杂度),又比文档级整体比对更精准。这种粒度选择在设计阶段就平衡了效率与准确性,是性能优化的基础。
  2. calculateSimilarity入口先通过cleanText完成干扰字符过滤、标点标准化,确保进入核心计算(如 LCS、词频分析)的文本已剔除噪声,减少无效计算(如对干扰字符的比对)。
  3. 将计算流程拆分为 “文本清洗→句子分割→句子匹配→词频分析→结果整合”,每个方法专注单一功能(如calculateLCSLength仅负责最长公共子序列计算)。这种设计减少了重复代码,便于缓存复用中间结果(如分词结果可在句子匹配和词频计算中共享)。
  4. 代码中对空文本、空句子列表等特殊情况做了提前判断(if (origSentences.isEmpty() || plagSentences.isEmpty()) return 0.0),避免无效的循环和计算,减少不必要的性能损耗。
  5. 核心采用 LCS 算法而非编辑距离,在句子级比对中 LCS 更关注 “相似部分的连续性”,计算步骤更简洁;同时用余弦相似度而非 Jaccard 系数计算词频,更适合处理词汇分布稀疏的文本场景。

3,性能分析图:

c979e1302f09f14a9930fc07e0aa2114

badcf084370379d8816703f144ebb1cc

在这之中 calculateSentenceSimilarity是计算资源消耗最大的函数

四,计算模块部分单元测试展示

以下三个函数是需要重点验证的核心功能,直接影响相似度计算的准确性:

  1. calculateTwoSentencesSimilarity(String s1, String s2)
    • 功能:计算两个句子的基础相似度(基于同义词归一化和最长公共子序列 LCS)。
    • 测试重点:验证同义词替换后 LCS 算法的准确性,确保语义相似的句子得到合理分数。
  2. calculateWordFrequencySimilarity(String text1, String text2)
    • 功能:通过词频向量的余弦相似度,衡量整体词汇分布的相似性。
    • 测试重点:验证词频统计、向量构建及余弦公式的正确性,确保词汇重叠度与分数正相关。
  3. calculateSimilarity(String orig, String plag)
    • 功能:综合句子级相似度(70% 权重)和词频相似度(30% 权重),输出最终查重结果。
    • 测试重点:验证权重计算逻辑,确保整体结果符合 “部分抄袭部分得分、完全抄袭得满分” 的预期。

部分测试函数代码:

image-20250923182007621

  1. testSplitIntoSentences函数
    • 测试对象:TextProcessor类的splitIntoSentences方法。
    • 功能验证:该方法用于将一段文本按照中文的句号、感叹号、问号等标点符号分割成句子列表。测试用例中,输入包含不同标点的文本,期望分割后得到正确数量的句子,并且每个句子的内容符合预期;同时验证空文本输入时,返回空列表。
  2. testSynonymReplacement函数
    • 测试对象:SimilarityCalculator类的normalizeWords方法。
    • 功能验证:该方法用于将单词列表中的同义词替换为标准词汇。测试用例中,输入包含同义词的单词列表,期望替换后得到对应的标准词汇列表;同时验证输入非同义词的单词列表时,保持原词不变。

构建思路:

  1. testSplitIntoSentences数据构造
    • 正常文本场景:构造包含多种中文断句标点(句号、感叹号、问号)的文本,用于测试方法在常规文本分割时的准确性,确保能正确识别不同标点并分割出对应数量的句子。
    • 边界场景:构造空文本,测试方法在输入为空时的处理逻辑,期望返回空列表,验证方法对异常输入的鲁棒性。
  2. testSynonymReplacement数据构造
    • 同义词场景:选取常见的中文同义词,如 “周天” 与 “星期天”、“马铃薯” 与 “土豆” 等,构造单词列表,测试同义词替换功能是否正常生效。
    • 非同义词场景:选取没有同义词映射的单词,如 “测试”“代码”,构造单词列表,测试方法在遇到非同义词时是否能保持原词不变,确保方法不会错误替换非同义词。

五,计算模块部分异常处理说明

空文本输入异常

image-20250923185527603当用户输入空文本(如原文未填写、抄袭文为空白)时,calculateSimilarity() 应返回 0.0 作为默认结果,避免因空指针或除以零等问题导致计算异常。

posted @ 2025-09-23 19:01  pigyoung  阅读(9)  评论(0)    收藏  举报