精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-11-28
典型的KMP算法
|
|
返回顶楼 | |
发表时间:2011-11-28
最后修改:2011-11-28
aimilin6688 写道 import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; /** * 求N个字符串中的最大公子串 * 思路:先找出字符串中最短的那个字符串,然后依次取出最短字符串中的每个字符与其余字符串进行比较。 */ public class ShortString { //字符串列表中的最短字符串 public String shortStr(ArrayList<String> strings){ return Collections.min(strings, new Comparator<String>(){ @Override public int compare(String str1, String str2) { if(str1.length()<str2.length()) return -1; else if(str1.length()==str2.length()) return 0; else if(str1.length()>str2.length()) return 1; return 0; } }); } //判断字符串列表中的每个字符串是否包含指定字符串,如果有一个不包含就返回false public boolean contains(ArrayList<String> strings,String str){ for(String s:strings){ if(!s.contains(str)) return false; } return true; } //最短公共字符串 public String maxSubString(ArrayList<String> strings){ String maxStr ="";//最长的公字符串 String tempStr="";//临时变量 String minStr=shortStr(strings);//所有字符串中的最短字符串 int i = 0; for( i = 0;i<minStr.length();i++){ tempStr += minStr.charAt(i); if(contains(strings,tempStr)){ //新公子串长度大于原来公子串,maxStr重新赋值 if(maxStr.length()<tempStr.length()) maxStr = tempStr; } else { //如果剩余的字符数小于公子串长度,就没有必要再比较了 if(minStr.length()-i<maxStr.length()) break; tempStr = minStr.charAt(i)+""; } } return maxStr; } public static void main(String[] args) { ArrayList<String> strings = new ArrayList<String>(Arrays.asList("ababcghy","abcdeftdsfgsdg","abcdefsdf")); ShortString ss = new ShortString(); System.out.println("字符串列表:"+ strings); System.out.println("最短字符串:"+ss.shortStr(strings)); System.out.println("最长公子串:"+ss.maxSubString(strings)); } } 这个貌似挺不错,测试一下先…… |
|
返回顶楼 | |
发表时间:2011-11-28
首先,这个可以先排序,就算不排序的话,最好先求出长度最小的字符串,再和别的字符串比较
其次,因为这个是求最大公字串,所以从最长的公字串与其它的字符串比较,一旦有合适的,后面的就可以不用比了; 随便写了点小程序玩玩 public static void foo2(String[] strs){ long time=System.currentTimeMillis(); String first=strs[0]; int length=strs[0].length(); for(int i=1;i<strs.length;i++){ int leng=strs[i].length(); if(length>leng){ first=strs[i]; length=leng; } } /*char[] ones=first.toCharArray(); char[] twos=second.toCharArray(); int two=twos.length; int one=ones.length;*/ all: for(int i=length;i>0;i--){ for(int j=0;j<=length-i;j++){ String str=first.substring(j,j+i); for(int k=0;;){ if(k<strs.length){ if(strs[k].contains(str)){ k++; }else{ break; } }else{ System.out.println(str); System.out.println("耗时:"+(System.currentTimeMillis()-time)+"ms"); break all; } } } } } |
|
返回顶楼 | |
发表时间:2011-11-28
kidneyball 写道 aimilin6688 写道 import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; /** * 求N个字符串中的最大公子串 * 思路:先找出字符串中最短的那个字符串,然后依次取出最短字符串中的每个字符与其余字符串进行比较。 */ public class ShortString { //字符串列表中的最短字符串 public String shortStr(ArrayList<String> strings){ return Collections.min(strings, new Comparator<String>(){ @Override public int compare(String str1, String str2) { if(str1.length()<str2.length()) return -1; else if(str1.length()==str2.length()) return 0; else if(str1.length()>str2.length()) return 1; return 0; } }); } //判断字符串列表中的每个字符串是否包含指定字符串,如果有一个不包含就返回false public boolean contains(ArrayList<String> strings,String str){ for(String s:strings){ if(!s.contains(str)) return false; } return true; } //最短公共字符串 public String maxSubString(ArrayList<String> strings){ String maxStr ="";//最长的公字符串 String tempStr="";//临时变量 String minStr=shortStr(strings);//所有字符串中的最短字符串 int i = 0; for( i = 0;i<minStr.length();i++){ tempStr += minStr.charAt(i); if(contains(strings,tempStr)){ //新公子串长度大于原来公子串,maxStr重新赋值 if(maxStr.length()<tempStr.length()) maxStr = tempStr; } else { //如果剩余的字符数小于公子串长度,就没有必要再比较了 if(minStr.length()-i<maxStr.length()) break; tempStr = minStr.charAt(i)+""; } } return maxStr; } public static void main(String[] args) { ArrayList<String> strings = new ArrayList<String>(Arrays.asList("ababcghy","abcdeftdsfgsdg","abcdefsdf")); ShortString ss = new ShortString(); System.out.println("字符串列表:"+ strings); System.out.println("最短字符串:"+ss.shortStr(strings)); System.out.println("最长公子串:"+ss.maxSubString(strings)); } } 这个貌似挺不错,测试一下先…… 。。。已故: "abcabc", "cabcfffffff" 看来至少两重循环是跑不掉的了 |
|
返回顶楼 | |
发表时间:2011-11-28
kmp算法
|
|
返回顶楼 | |
发表时间:2011-11-28
最后修改:2011-11-28
贴一段代码, 供大家批评, 都是基本的思路, 没有滑头
如果对于算法非常感兴趣, 可以去这个网站挑战一下: http://projecteuler.net/ package com.tianxiaohui.art.question.arithmetic; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 问题来源: http://www.iteye.com/topic/1118325 * 面试题目:求N个字符串中的最大公子串,比如: * 1、abcde * 2、abefg * 3、werabc * 这三个字符串的最大公子串是ab * @author Eric.Tian */ public class MaxSharedSubString { public static void main(String[] args) { ArrayList<String> strings = new ArrayList<String>(Arrays.asList("abcdefsdfababcghy", "abcdeftdsfabcdefsdf", "abcdefsdf", "abcdabcdefsdfdg", "abcdabcdefsdfdgabcdabcdefsdfdgabcdabcdefsdfdg")); //ArrayList<String> strings = new ArrayList<String>(Arrays.asList("abcabc", "cabcfffffff")); long start = System.currentTimeMillis(); System.out.println(MaxSharedSubString.getMaxSharedSubString(strings)); System.out.println("Cost: " + (System.currentTimeMillis() - start)); } public static String getMaxSharedSubString(List<String> strs) { // 以最短字符串为基准去测试 String shortestStr = MaxSharedSubString.getShortestStr(strs); String maxSharedSubStr = ""; int j = 0; String tmpStr = ""; // 最短字符串的每个字符开头的字符 for (int i = 0; i < shortestStr.length(); i++) { // 从以这个字符开头的最长字符子串开始, 逐渐缩短, 但不能短于已经找到的最短串 for (j = shortestStr.length(); j > i & (j - i) > maxSharedSubStr.length(); j--) { tmpStr = shortestStr.substring(i, j); // Check 一下是不是都含有这个子串 if (MaxSharedSubString.ifAllHave(strs, tmpStr)) { maxSharedSubStr = tmpStr; } } } return maxSharedSubStr; } private static String getShortestStr(List<String> strs) { String tmpStr = strs.get(0); for (String str : strs) { if (str.length() > tmpStr.length()) { tmpStr = str; } } return tmpStr; } private static boolean ifAllHave(List<String> strs, String string) { for (String str : strs) { if (!str.contains(string)) { return false; } } return true; } } |
|
返回顶楼 | |
发表时间:2011-11-28
算法书上有,忘记了,大概叫longest common subsuquence。是关于动态规划的一个问题。
|
|
返回顶楼 | |
发表时间:2011-11-29
这不是LCS,这是后缀树组问题
|
|
返回顶楼 | |
发表时间:2011-11-29
说动态规划的兄弟,请分析你们的动态递归解。这貌似不是那么容易动态规划的!这里有个动态规划之最长公共子序列的例子,http://songzi0206.iteye.com/blog/1160277,比较之后发现,对于本帖的例子,第一个动态分析算式都不成立。
|
|
返回顶楼 | |
发表时间:2011-11-29
kidneyball 写道 kidneyball 写道 aimilin6688 写道 import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; /** * 求N个字符串中的最大公子串 * 思路:先找出字符串中最短的那个字符串,然后依次取出最短字符串中的每个字符与其余字符串进行比较。 */ public class ShortString { //字符串列表中的最短字符串 public String shortStr(ArrayList<String> strings){ return Collections.min(strings, new Comparator<String>(){ @Override public int compare(String str1, String str2) { if(str1.length()<str2.length()) return -1; else if(str1.length()==str2.length()) return 0; else if(str1.length()>str2.length()) return 1; return 0; } }); } //判断字符串列表中的每个字符串是否包含指定字符串,如果有一个不包含就返回false public boolean contains(ArrayList<String> strings,String str){ for(String s:strings){ if(!s.contains(str)) return false; } return true; } //最短公共字符串 public String maxSubString(ArrayList<String> strings){ String maxStr ="";//最长的公字符串 String tempStr="";//临时变量 String minStr=shortStr(strings);//所有字符串中的最短字符串 int i = 0; for( i = 0;i<minStr.length();i++){ tempStr += minStr.charAt(i); if(contains(strings,tempStr)){ //新公子串长度大于原来公子串,maxStr重新赋值 if(maxStr.length()<tempStr.length()) maxStr = tempStr; } else { //如果剩余的字符数小于公子串长度,就没有必要再比较了 if(minStr.length()-i<maxStr.length()) break; tempStr = minStr.charAt(i)+""; } } return maxStr; } public static void main(String[] args) { ArrayList<String> strings = new ArrayList<String>(Arrays.asList("ababcghy","abcdeftdsfgsdg","abcdefsdf")); ShortString ss = new ShortString(); System.out.println("字符串列表:"+ strings); System.out.println("最短字符串:"+ss.shortStr(strings)); System.out.println("最长公子串:"+ss.maxSubString(strings)); } } 这个貌似挺不错,测试一下先…… 。。。已故: "abcabc", "cabcfffffff" 看来至少两重循环是跑不掉的了 //如果剩余的字符数小于公子串长度,就没有必要再比较了 if(minStr.length()-i<maxStr.length()) break; tempStr = minStr.charAt(i)+""; 这个有问题吧: 1. 剩余字符数小于当前公子串长度,并不代表剩余的字符就没用了,如abcde(实际的最大公子串是bcde),当发现abc不匹配的时候,难道就要放弃? 2. 一次搜索失败后再次搜索时最小字符串的起始字符偏移不正确,如:发现abc不匹配时(假如这是第1次搜索即 i从0开始),i=2,重新搜索时i应该从1开始 |
|
返回顶楼 | |