2021-12-23每日一题
给你一个字符串 s
,考虑其所有 重复子串 :即,s
的连续子串,在 s
中出现 2 次或更多次。这些出现之间可能存在重叠。
返回 任意一个 可能具有最长长度的重复子串。如果 s
不含重复子串,那么答案为 ""
。
示例 1:
输入:s = "banana" 输出:"ana"
示例 2:
输入:s = "abcd" 输出:""
提示:
2 <= s.length <= 3 * 104
s
由小写英文字母组成
1 public String longestDupSub(String s) { 2 int[] dp=new int[s.length()]; 3 int index=-1,max=0; 4 if (s.charAt(0)==s.charAt(1)){ 5 dp[1]=1; 6 index=0; 7 max=1; 8 }else 9 { 10 dp[1]=0; 11 } 12 for (int i = 2; i < s.length(); i++) { 13 if (s.substring(0,i).contains(s.substring(i-dp[i-1],i+1))) 14 { 15 dp[i]=dp[i-1]+1; 16 max=dp[i]; 17 index=i-dp[i-1]; 18 }else{ 19 dp[i]=dp[i-1]; 20 } 21 } 22 if (index==-1) return ""; 23 return s.substring(index,index+max); 24 }
自己写的动态规划,超时
贴个大佬写的,二分查找+字符串哈希
1 long[] h, p; 2 public String longestDupSubstring(String s) { 3 int P = 1313131, n = s.length(); 4 h = new long[n + 10]; p = new long[n + 10]; 5 p[0] = 1; 6 for (int i = 0; i < n; i++) { 7 p[i + 1] = p[i] * P; 8 h[i + 1] = h[i] * P + s.charAt(i); 9 } 10 String ans = ""; 11 int l = 0, r = n; 12 while (l < r) { 13 int mid = l + r + 1 >> 1; 14 String t = check(s, mid); 15 if (t.length() != 0) l = mid; 16 else r = mid - 1; 17 ans = t.length() > ans.length() ? t : ans; 18 } 19 return ans; 20 } 21 String check(String s, int len) { 22 int n = s.length(); 23 Set<Long> set = new HashSet<>(); 24 for (int i = 1; i + len - 1 <= n; i++) { 25 int j = i + len - 1; 26 long cur = h[j] - h[i - 1] * p[j - i + 1]; 27 if (set.contains(cur)) return s.substring(i - 1, j); 28 set.add(cur); 29 } 30 return ""; 31 }