首页>代码>jsp+servlet开发java web学生信息管理系统,简单增删改查,作业查重系统,论文查重>/StudentManage/src/dao/JaroWinklerDistanceDao.java
package dao; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; public class JaroWinklerDistanceDao { private static final String html_seperator="\n"; private static final String sentence_seperator="[,.;!:,。;!:]"; //将一段文字切割成若干句 public static String[] split(String src) { List<String> result=new ArrayList<>(); String []htmls=src.split(html_seperator); for (String s:htmls){ for (String s2:s.split(sentence_seperator)){ result.add(s2); } } String []results=new String[result.size()]; result.toArray(results);//集合转数组 return results; } //清晰字符串除杂消除干扰 public static String[] clean(String []src) { for (int i=0;i<src.length;i++) { src[i]=clean(src[i]);//调用清楚非数字、字母、中文的方法,赋予新数组 } return src; } //清除非数字、字母、中文 public static String clean(String src) { return src.replaceAll("[^a-zA-Z0-9\\u4e00-\\u9fa5]",""); } //检测两个作业内容的相似率 public static float detect(String des,String src) { float resultFloat=0.00f; float tmp = 0.00f; float sm = 0.00f; //分语义行切割作业内容 String desArray[]=split(des); String srcArray[]=split(src); //对作业内容中非自然语言进行清洗除杂 desArray=clean(desArray); srcArray=clean(srcArray); /*System.out.println(desArray.length+" "+srcArray.length); for(String s:desArray){ System.out.println(s); }*/ for (String s:desArray){ sm = 0.00f; for(String pr:srcArray){ tmp = 0.00f; tmp = getDistance(s,pr); sm = sm>tmp?sm:tmp; // System.out.println("tmp:"+tmp); } // System.out.println(sm); resultFloat += sm; } // System.out.println(sm); resultFloat/=desArray.length; return resultFloat; } private static int max(int length, int length2) { // TODO Auto-generated method stub return length>length2 ? length:length2; } //将小数转化为百分数的字符串 public static String transferFloatToPersentString(float f) { String result; f*=10000; int t1=(int)f; result=(((float)t1)/100)+"%"; return result; } public static String check() { Date start=new Date(); //将路径存在字符串变量中,调用in方法读取。 String path1 = "D:/tmp/论文库.txt"; String path2 = "D:/tmp/学生论文.txt"; String tar=in(path2); String src=in(path1); String sim = transferFloatToPersentString(detect(tar,src)); System.out.println("相似度:" + sim); Date end=new Date(); System.out.println("花费时间:"+(end.getTime()-start.getTime())+"毫秒"); return sim; } public static String in(String path) { String str=""; File file=new File(path); try { FileInputStream in=new FileInputStream(file); // size 为字串的长度 ,这里一次性读完 int size=in.available(); byte[] buffer=new byte[size]; in.read(buffer); in.close(); str=new String(buffer,"UTF-8"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } return str; /* 按行读对于要处理的格式化数据是一种读取的好方式 */ /*int len=0; StringBuffer str=new StringBuffer(""); File file=new File("D:\\tmp\\论文.txt"); try { FileInputStream is=new FileInputStream(file); InputStreamReader isr= new InputStreamReader(is,"utf-8"); BufferedReader in= new BufferedReader(isr); String line=null; while( (line=in.readLine())!=null ) { if(len != 0) // 处理换行符的问题 { str.append("\r\n"+line); } else { str.append(line); } len++; } in.close(); is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return str.toString();*/ } //JaroWinklerDistance算法 private static float threshold = 0.7f; private static int[] matches(String s1, String s2) { String max, min; if (s1.length() > s2.length()) { max = s1; min = s2; } else { max = s2; min = s1; } // 两个分别来自s1和s2的字符如果相距不超过 floor(max(|s1|,|s2|) / 2) -1, 我们就认为这两个字符串是匹配的 // 因此,查找时,超过此距离则停止 int range = Math.max(max.length() / 2 - 1, 0); // 短的字符串, 与长字符串匹配的索引位 int[] matchIndexes = new int[min.length()]; Arrays.fill(matchIndexes, -1); // 长字符串匹配的标记 boolean[] matchFlags = new boolean[max.length()]; // 匹配的数目 int matches = 0; // 外层循环,字符串最短的开始 for (int mi = 0; mi < min.length(); mi++) { char c1 = min.charAt(mi); // 可能匹配的距离,包括从给定位置从前查找和从后查找 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max .length()); xi < xn; xi++) { // 排除被匹配过的字符,若找到匹配的字符,则停止 if (!matchFlags[xi] && c1 == max.charAt(xi)) { matchIndexes[mi] = xi; matchFlags[xi] = true; matches++; break; } } } // 记录min字符串里匹配的字符串,保持顺序 char[] ms1 = new char[matches]; // 记录max字符串里匹配的字符串,保持顺序 char[] ms2 = new char[matches]; for (int i = 0, si = 0; i < min.length(); i++) { if (matchIndexes[i] != -1) { ms1[si] = min.charAt(i); si++; } } for (int i = 0, si = 0; i < max.length(); i++) { if (matchFlags[i]) { ms2[si] = max.charAt(i); si++; } } // 查找换位的数目 int transpositions = 0; for (int mi = 0; mi < ms1.length; mi++) { if (ms1[mi] != ms2[mi]) { transpositions++; } } // 查找相同前缀的数目 int prefix = 0; for (int mi = 0; mi < min.length(); mi++) { if (s1.charAt(mi) == s2.charAt(mi)) { prefix++; } else { break; } } // 返回匹配数目(m),换位的数目(t),相同的前缀的数目,字符串最长 return new int[] { matches, transpositions / 2, prefix, max.length() }; } public static float getDistance(String s1, String s2) { int[] mtp = matches(s1, s2); // 返回匹配数目(m) float m = (float) mtp[0]; if (m == 0) { return 0f; } // Jaro Distance float j = ((m / s1.length() + m / s2.length() + (m - mtp[1]) / m)) / 3; // 计算Jaro-Winkler Distance, 这里调整分数的因数=Math.min(0.1f, 1f / mtp[3]) float jw = j < getThreshold() ? j : j + Math.min(0.1f, 1f / mtp[3]) * mtp[2] * (1 - j); return jw; } /** * Sets the threshold used to determine when Winkler bonus should be used. * Set to a negative value to get the Jaro distance. * @param threshold the new value of the threshold */ public void setThreshold(float threshold) { this.threshold = threshold; } /** * Returns the current value of the threshold used for adding the Winkler bonus. * The default value is 0.7. * @return the current value of the threshold */ public static float getThreshold() { return threshold; } }

呵呵喝 LV4
2024年3月11日
杨豫川 LV12
2024年1月12日
asddwh LV13
2023年12月29日
微信网友_6680567232876544 LV8
2023年10月8日
hongdongdong LV14
2023年6月27日
tianyuboy111 LV3
2023年5月20日
liuchang183 LV5
2023年4月22日
蹇金金 LV7
2023年3月14日
北方菜 LV11
2022年12月30日
Korol27 LV3
2022年12月16日

dongandmin LV8
2024年12月27日
yimaoermao LV1
2024年11月28日
xiaoaitx LV8
2024年11月19日
微信网友_6520355827929088 LV2
2024年11月18日
angaochong LV5
2024年10月16日
breeza
2024年10月9日
暂无贡献等级
时光海 LV2
2024年6月30日
破剑茶寮 LV4
2024年6月26日
liyan54188 LV2
2024年6月25日
zzk3085000785
2024年6月20日
暂无贡献等级