Problem Description: 给定一个字符串,找出其中最长的重复出现的字符串,并且给出其首次出现的位置。 输入 输入包含多组测试数据; 每组测试字符串占一行。 数据保证: 50%的字符串长度在[0,100], 100%的字符串长度[0,1000]。 输出 对于每组测试数据,请输出最长的重复出现的字符串和其首次出现的位置。 每组输出占一行,格式为:首次出现位置 最长的重复字符串,中间用空格分隔。 如果没有重复字符串,输出-1。 样例输入 abcdefg yetfgvyabcdabjcabcsdfeg yetfabc defhjihjabc defyy 样例输出 -1 7 abc 4 abc def
解题思路:
原字符串 -> 后缀数组 -> 备份后缀数组 -> 对后缀数组排序 -> 对排序后的数组,两两比较相邻元素,找到其最长公共前缀子串,并记录最大长度和下标 -> 组合出最长重复子串内容,并由备份后缀数组,求出首次出现的位置。
Java 代码:
import java.util.Arrays; import java.util.Scanner; public class Main { public String find(String str){ int len = str.length(); String[] array = new String[len]; for(int i = 0; i < str.length(); i++) { // 产生后缀数组 array[i] = str.substring(i); } String[] copyArray = new String[len]; System.arraycopy(array, 0, copyArray, 0, array.length); // 备份排序前的数组元素。 Arrays.sort(array); int max = 0; int index = 0; for (int i = 0; i < array.length-1; i++) { // 两两比较相邻的字符串,找到最长共同前缀子串 String tmp1 = array[i]; String tmp2 = array[i+1]; int count = 0; for (int j = 0; j < tmp1.length() && j < tmp2.length(); j++) { if(tmp1.charAt(j) == tmp2.charAt(j)) { count++; if(count > max) { max = count; index = i; } } else { //不是共同前缀时,跳出循环 break; } } } if(max == 0) return "-1"; else { StringBuilder sb = new StringBuilder(); String tmp = array[index].substring(0, max); //找到最大重复子串的内容 for (int i = 0; i < copyArray.length; i++) { // 找到最大重复子串在排序前的数组中元素的前缀的下标 if (copyArray[i].startsWith(tmp)) { sb.append(i); break; } } sb.append(" "); sb.append(tmp); return sb.toString(); //返回结果 } } public static void main(String[] args) throws Exception{ Scanner cin = new Scanner(System.in); while (cin.hasNext()) { String str = cin.nextLine(); String result = new Main().find(str); System.out.println(result); } cin.close(); } }
原文:http://www.cnblogs.com/lasclocker/p/4881127.html