Java 连接两个不相交的字符串

Java 连接两个不相交的字符串,java,string,string-concatenation,Java,String,String Concatenation,我需要将两个字符串连接到另一个字符串中,而不交叉(就最后一个/第一个单词而言) 例如: “一些小d”+“小狗很漂亮”=“一些小狗很漂亮” “我爱你”+“爱”=“我爱你爱” 在Java中最有效的方法是什么?最简单的方法是:使用后缀(“Some little d”、“ome little d”、“me little d”…)迭代第一个字符串,然后使用.startsWith测试第二个字符串。找到匹配项后,将第一个字符串的前缀连接到第二个字符串 代码如下: String overlappingConca

我需要将两个字符串连接到另一个字符串中,而不交叉(就最后一个/第一个单词而言)

例如:

“一些小d”+“小狗很漂亮”=“一些小狗很漂亮”

“我爱你”+“爱”=“我爱你爱”


在Java中最有效的方法是什么?

最简单的方法是:使用后缀(“Some little d”、“ome little d”、“me little d”…)迭代第一个字符串,然后使用
.startsWith
测试第二个字符串。找到匹配项后,将第一个字符串的前缀连接到第二个字符串

代码如下:

String overlappingConcat(String a, String b) {                              
  int i;
  int l = a.length();
  for (i = 0; i < l; i++) {
    if (b.startsWith(a.substring(i))) {
      return a.substring(0, i) + b;
    }
  }
  return a + b;
}
String overlappingConcat(字符串a、字符串b){
int i;
int l=a.长度();
对于(i=0;i

这里最大的效率问题是在
子字符串中创建新字符串。实现自定义的
stringMatchFrom(a,b,aOffset)
应该可以改进它,而且很简单。

我们开始吧-如果第一个字符串甚至不包含第二个字符串的第一个字母,只需返回串联即可。否则,在第二个字符串上从最长到最短,查看第一个字符串是否以它结尾。如果是,请返回非重叠部分,否则请尝试短一个字母

 public static String docat(String f, String s) {
   if (!f.contains(s.substring(0,1)))
     return f + s;
   int idx = s.length();
   try {
     while (!f.endsWith(s.substring(0, idx--))) ;
   } catch (Exception e) { }
   return f + s.substring(idx + 1);
 }

 docat("Some little d", "little dogs are so pretty");
 -> "Some little dogs are so pretty"
 docat("Hello World", "World")
 -> "Hello World"
 docat("Hello", "World")
 -> "HelloWorld"
编辑:作为对注释的响应,这里有一个使用数组的方法。我不知道如何正确地进行压力测试,但在我的测试中没有一个超过1毫秒

public static String docat2(String first, String second) {
  char[] f = first.toCharArray();
  char[] s = second.toCharArray();
  if (!first.contains("" + s[0]))
    return first + second;
  int idx = 0;
  try {
    while (!matches(f, s, idx)) idx++;
  } catch (Exception e) { }
  return first.substring(0, idx) + second;
}

private static boolean matches(char[] f, char[] s, int idx) {
  for (int i = idx; i <= f.length; i++) {
    if (f[i] != s[i - idx])
      return false;
  }
  return true;
}
公共静态字符串docat2(字符串第一,字符串第二){
char[]f=first.toCharArray();
char[]s=second.toCharArray();
如果(!first.contains(“+s[0]))
返回第一个+第二个;
int-idx=0;
试一试{
而(!matches(f,s,idx))idx++;
}捕获(例外e){}
返回第一个。子字符串(0,idx)+第二个;
}
私有静态布尔匹配(char[]f,char[]s,int idx){

对于(int i=idx;i下面的代码似乎适用于第一个示例。我没有对它进行广泛的测试,但你明白了。它基本上会搜索
firstString
secondString
的所有第一个字符,因为这是唯一可能发生重叠的地方。然后它会检查第一个字符串的st是第二个字符串的开始。当没有发现重叠时,代码可能包含一些错误,…但这更多的是我的答案的说明

String firstString = "Some little d";
String secondString = "little dogs are so pretty";
String startChar = secondString.substring( 0, 1 );
int index = Math.max( 0, firstString.length() - secondString.length() );
int length = firstString.length();
int searchedIndex = -1;
while ( searchedIndex == -1 && ( index = firstString.indexOf( startChar, index ) )!= -1 ){
  if ( secondString.startsWith( firstString.substring( index, length ) ) ){
    searchedIndex = index;
  }
}
String result = firstString.substring( 0, searchedIndex ) + secondString;

使用regionMatches()方法可以避免创建不必要的子字符串

isBlank(CharSequence)
join(T..)
left(String,int)
是来自Apache Commons的方法

public static String joinOverlap(String s1, String s2) {
    if(isBlank(s1) || isBlank(s2)) { //empty or null input -> normal join
        return join(s1, s2);
    }

    int start = Math.max(0, s1.length() - s2.length());

    for(int i = start; i < s1.length(); i++) { //this loop is for start point
        for(int j = i; s1.charAt(j) == s2.charAt(j-i); j++) { //iterate until mismatch
            if(j == s1.length() - 1) { //was it s1's last char?
                return join(left(s1, i), s2);
            }
        }
    }

    return join(s1, s2); //no overlapping; do normal join
}
公共静态字符串joinOverlap(字符串s1、字符串s2){
如果(isBlank(s1)| | isBlank(s2)){//empty或null输入->正常连接
返回连接(s1,s2);
}
int start=Math.max(0,s1.length()-s2.length());
对于(inti=start;i
创建第一个字符串的一个后缀,然后从第二个字符串开头的根字符遍历树,并跟踪找到的最长后缀

这应该是作为第二个字符串前缀的第一个字符串的最长后缀。请删除后缀,然后追加第二个字符串


这应该是线性时间,而不是循环和比较所有后缀所需的二次时间。

这不是很有效,我正在寻找更强大的功能。这是一个很好的例子,但OP想要更有效的功能。对于非常小的狗来说,这仍然会创建很多临时字符串。继续e可以通过首先通过
String.tocharray()
获取字符串的
char[]
数组,并实现一个自定义的
endsWith()
来避免这种情况。@user268396:新版本更适合您吗?我想使用这个算法(char[/code>)。似乎简单且快速。谢谢。如果您有非常大的字符串,则创建复杂的映射对象可能是一个巨大的成功。但是对于大小适中的字符串,设置后缀树所需的时间和内存似乎不太可能带来回报。对于小N,简单的O(N**2)算法通常比更复杂的O(N)算法更有效。实时会将大常量(设置时间)考虑在内,即使顺序统计数据不考虑。感谢您让我知道什么是后缀树,这对于这个问题非常重要(字符串多且短),但我认为对于其他问题可能是好的。
public static String joinOverlap(String s1, String s2) {
    if(isBlank(s1) || isBlank(s2)) { //empty or null input -> normal join
        return join(s1, s2);
    }

    int start = Math.max(0, s1.length() - s2.length());

    for(int i = start; i < s1.length(); i++) { //this loop is for start point
        for(int j = i; s1.charAt(j) == s2.charAt(j-i); j++) { //iterate until mismatch
            if(j == s1.length() - 1) { //was it s1's last char?
                return join(left(s1, i), s2);
            }
        }
    }

    return join(s1, s2); //no overlapping; do normal join
}