軟工作業2:個人專案-論文查重
GitHub連結: github
課程資訊
- 課程: 計科22級2班 - 廣東工業大學
- 作業要求: 作業要求
- 目標: 完成個人專案-論文查重;學會寫單元測試
一、PSP表格
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 60 | 30 |
Estimate | 估計這個任務需要多少時間 | 30 | 60 |
Development | 開發 | 300 | 420 |
Analysis | 需求分析 (包括學習新技術) | 60 | 30 |
Design Spec | 生成設計文件 | 60 | 60 |
Design Review | 設計複審 | 15 | 10 |
Coding Standard | 程式碼規範 | 15 | 10 |
Design | 具體設計 | 30 | 60 |
Coding | 具體編碼 | 30 | 60 |
Code Review | 程式碼複審 | 15 | 10 |
Test | 測試(自我測試,修改程式碼,提交修改) | 15 | 60 |
Reporting | 報告 | 60 | 120 |
Test Report | 測試報告 | 30 | 60 |
Size Measurement | 計算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事後總結, 並提出過程改進計劃 | 10 | 20 |
合計 | 740 | 1020 |
二、設計與開發
編碼規範
- 阿里巴巴開發規範外掛
2.1 開發環境
- 作業系統: Windows
- 程式語言: JDK 1.8
2.2 開發工具
- Maven包管理工具
- IDE: IDEA 2022.3.1
- 效能分析工具: JProfiler 11.1.4
2.3 專案依賴
- JUnit測試框架
- Jieba-Java中文分詞庫
2.4 演算法設計說明
longestCommonSubsequence (LCS) 演算法
-
動態規劃:
- 使用動態規劃來計算 LCS。建立一個二維陣列
dp
,其中dp[i][j]
表示前i
個字元和前j
個字元的 LCS 長度。 - 遍歷兩個字串的每個字元:
- 如果字元相同,則 LCS 長度為
dp[i-1][j-1] + 1
。 - 如果字元不同,則 LCS 長度為
Math.max(dp[i-1][j], dp[i][j-1])
,即取左邊或上邊的最大值。
- 如果字元相同,則 LCS 長度為
- 使用動態規劃來計算 LCS。建立一個二維陣列
-
時間複雜度:
- LCS 演算法的時間複雜度為 O(m × n),其中 m 和 n 分別是兩個字串的長度。
-
空間複雜度:
- 空間複雜度為 O(m × n),用於儲存動態規劃表。如果需要最佳化空間,可以只保留當前行和上一行的資料。
-
優點:
- LCS 演算法簡單直觀,適合用於文字相似度檢測。
- 結果能夠有效反映文字之間的相似性。
-
缺點:
- 對於較長的文字,計算複雜度較高,可能導致效能問題。
- 僅依賴於字元匹配,無法捕捉文字的語義資訊。
2.5 介面設計與實現過程
類設計與實現過程
1. 檔案處理類 (FileHandler
)
設計目的
FileHandler
類的主要目的是封裝檔案操作,以便於讀取和寫入文字檔案。透過將檔案操作集中在一個類中,程式碼變得更加模組化,便於維護和重用。
實現過程
-
讀取檔案:
- 使用
Files.readAllBytes
方法讀取檔案內容,並轉換為字串。 - 處理可能的
IOException
,確保檔案讀取的安全性。
- 使用
-
寫入檔案:
- 使用
Files.writeString
方法將內容寫入檔案。新增了StandardOpenOption.APPEND
選項以確保內容被追加,而不是覆蓋。 - 新增換行符,確保每次追加內容都在新的一行開始。
- 使用
2. 相似度計算類 (SimilarityCalculator
)
設計目的
SimilarityCalculator
類專注於計算文字之間的相似度,主要採用最長公共子序列(LCS)演算法。將相似度計算邏輯與檔案處理分開,有助於清晰地劃分責任。
實現過程
-
計算相似度:
- 定義
calculateSimilarity
方法,接收兩個字串引數(原始文字和抄襲文字)。 - 呼叫
longestCommonSubsequence
方法計算 LCS 長度。 - 使用公式計算相似度,並透過
DecimalFormat
確保結果保留兩位小數。
- 定義
-
LCS 演算法實現:
- 使用兩個一維陣列
prev
和curr
,將空間複雜度最佳化為O(n)
。 - 透過動態規劃遍歷兩個字串,更新陣列以計算 LCS 長度。
- 使用兩個一維陣列
主程式類 (PaperCheck
)
設計目的
PaperCheck
類作為程式的入口,負責協調檔案處理和相似度計算的工作。它整合了其他兩個類,形成完整的程式。
實現過程
- 主方法:
- 在
main
方法中建立FileHandler
和SimilarityCalculator
的例項。 - 呼叫
FileHandler
的readFile
方法讀取原始文字和抄襲文字。 - 呼叫
SimilarityCalculator
的calculateSimilarity
方法計算相似度。 - 將相似度結果格式化並寫入輸出檔案,同時列印到控制檯。
- 在
三、測試與效能分析
3.1 測試
LCE演算法最佳化:
-之前的實現:使用了一個二維陣列 dp,其大小為 m x n,其中 m 和 n 是兩個字串的長度。這在處理較大字串時,會佔用大量記憶體。
-最佳化後的實現:只使用兩個一維陣列prev和curr,分別儲存當前行和上一行的狀態。這樣,空間複雜度從O(m*n)降低到O(n),顯著減少了記憶體使用。
執行時JProfiler分析
覆蓋率
部分測試樣例:測試LCS演算法實現,主要透過正常引數和空引數進行測試
可能的異常
命令列引數不規則
直接判斷處理
文字檔案為空
直接判斷然後結束程式