個人專案———論文查重
這個作業屬於哪個課程 | 計科12班 |
---|---|
這個作業的要求在哪裡 | 作業要求 |
這個作業的目標 | 實現論文查重,給定原檔案和抄襲的檔案,輸出二者的相似度到答案檔案中 |
GitHub連結:github
1.題目要求
題目:論文查重
描述如下:
設計一個論文查重演算法,給出一個原文檔案和一個在這份原文上經過了增刪改的抄襲版論文的檔案,在答案檔案中輸出其重複率。
原文示例:今天是星期天,天氣晴,今天晚上我要去看電影。
抄襲版示例:今天是周天,天氣晴朗,我晚上要去看電影。
要求輸入輸出採用檔案輸入輸出,規範如下:
從命令列引數給出:論文原文的檔案的絕對路徑。
從命令列引數給出:抄襲版論文的檔案的絕對路徑。
從命令列引數給出:輸出的答案檔案的絕對路徑。
我們提供一份樣例,課堂上下發,上傳到班級群,使用方法是:orig.txt是原文,其他orig_add.txt等均為抄襲版論文。
注意:答案檔案中輸出的答案為浮點型,精確到小數點後兩位
2.專案開發
2.1開發環境:
語言:JAVA
編譯器:JDk-21
工具:IntelliJ IDEA
2.2專案結構
2.3專案模組介紹
- Abnormal---------處理各種異常類
- calcuture_Utils--主要演算法的實現
- In_Out_Utils-----檔案的輸入和輸出
- main-------------啟動類主函式
- test-------------對其他各種類的測試
2.4專案的設計與實現過程(流程圖)
2.5主要演算法
①simhash演算法:使用HanLP從文字中提取關鍵詞,並儲存在列表,遍歷列表的關鍵詞,使用MD5演算法對每個關鍵詞計算hash值,並對結果進行加權,與減權處理,再透過降維處理得到文字的simhash值。
實現程式碼:
點選檢視程式碼
public class Calculate_SimHash {
public static String gethash(String text){
try {
//首先建立物件,指定使用MD5演算法
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
//將字串轉換為UTF-8編碼的位元組陣列,計算雜湊值,以二進位制字串形式返回
return new BigInteger(1, messageDigest.digest(text.getBytes(StandardCharsets.UTF_8))).toString(2);
}catch (Exception e){
//丟擲異常
throw new RuntimeException("操作失敗",e);
}
}
//設計方法——計算文字的simHash值
public static String getSimHash(String text) throws Abnormal_TextShort {
//驗證文字是否過短,過短則丟擲異常
if(text.length() < 100) throw new Abnormal_TextShort("文字長度過短");
//初始化整形陣列作為特徵向量
int[] eigenvector = new int[128];
//使用HanLP從文字中提取關鍵詞,並儲存在列表中
List<String> keywords = HanLP.extractKeyword(text, text.length());
int size = keywords.size();
System.out.println("關鍵字的數量:" + size);
int i = 0;//初始化一個計數器
//遍歷每個關鍵詞,根據權重調整
for(String keyword : keywords){
//獲取關鍵詞的Hash值,並將其轉換為一個物件
//System.out.println(keyword);
//System.out.println(gethash(keyword));
StringBuilder keywordHash = new StringBuilder(gethash(keyword));
//如果關鍵字的雜湊值長度小於128,則在默末尾用0補齊
if(keywordHash.length() < 128){
int temp = 128 - keywordHash.length();
for(int j = 0; j < temp; j++){
keywordHash.append("0");
}
}
//加權
for(int j = 0; j < eigenvector.length; j++){
//如果當前位是1,則根據位置進行加權,否則根據位置減權
if(keywordHash.charAt(j) == '1'){
eigenvector[j] += (10 - (i / (size / 10)));
}else{
eigenvector[j] -= (10 - (i / (size / 10)));
}
}
i++;
}
//遍歷特徵向量每個元素根據正負值來構建轉化為SimHash
StringBuilder simHash = new StringBuilder();
for(int element : eigenvector){
simHash.append(element > 0 ? "1" : "0");
//System.out.println(element);
}
return simHash.toString();
}
}
②similarity演算法:對於得到的兩個文字的simhash值,計算二者的海明距離,並透過海明距離代入公式得到進計算相似度。
實現程式碼:
點選檢視程式碼
package com.Calculate_Utils;
public class Calculate_Similarity {
public static int getHammingDistance(String simHash1, String simHash2)
{
//設計方法——透過hash值來計算海明距離
int Haiming_distance = 0;
if(simHash1.length()!=simHash2.length()){
return -1;
} else {
for(int i = 0; i < simHash1.length(); i++){
//迴圈比較二者的字元
if(simHash1.charAt(i) != simHash2.charAt(i)) {
//遍歷二者字元,如果不同,距離加一
Haiming_distance += 1;
}
}
}
System.out.println("海明距離為:" + Haiming_distance);//輸出海明距離
return Haiming_distance;
}
public static double getSimilarity(String simHash1, String simHash2)
{
//計算海明距離
int distance = getHammingDistance(simHash1, simHash2);
//透過海明距離計算相似度
System.out.println("相似度為:" + (100 - (double)(distance * 100) / 128));
return (100 - (double)(distance * 100) / 128);
}
}
2.6異常處理
本專案對三種異常進行捕捉處理分別為:
①讀取和寫入檔案發生錯誤的異常。
②提供路徑引數小於三個(即原檔案,抄襲檔案,答案檔案)的異常。
③輸入的文字過短的異常。
3.專案類測試
3.1讀檔案File_Input.java的測試
測試結果:
3.2寫檔案File_Output.java的測試
測試結果:
3.3simhash演算法的測試
測試結果:
3.4主函式main.java的測試
測試結果:
3.5傳入的引數過少的異常測試
測試結果:
3.6文字過短的異常測試
測試結果:
3.7檔案不存在的異常測試
測試結果:
4.效能分析(本專案採用了JProfiler來分析)