首页>代码>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
3月11日
杨豫川 LV12
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日
最近浏览更多
yimaoermao LV1
11月28日
xiaoaitx LV4
11月19日
微信网友_6520355827929088 LV2
11月18日
angaochong LV5
10月16日
breeza
10月9日
暂无贡献等级
时光海 LV2
6月30日
破剑茶寮 LV4
6月26日
liyan54188 LV2
6月25日
zzk3085000785
6月20日
暂无贡献等级
TY0165 LV20
6月19日