[Swift]LeetCode1044. 最长重复子串 | Longest Duplicate Substring
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10852170.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
Given a string S
, consider all duplicated substrings: (contiguous) substrings of S that occur 2 or more times. (The occurrences may overlap.)
Return any duplicated substring that has the longest possible length. (If S
does not have a duplicated substring, the answer is ""
.)
Example 1:
Input: "banana" Output: "ana"
Example 2:
Input: "abcd" Output: ""
Note:
2 <= S.length <= 10^5
S
consists of lowercase English letters.
给出一个字符串 S
,考虑其所有重复子串(S
的连续子串,出现两次或多次,可能会有重叠)。
返回任何具有最长可能长度的重复子串。(如果 S
不含重复子串,那么答案为 ""
。)
示例 1:
输入:"banana" 输出:"ana"
示例 2:
输入:"abcd" 输出:""
提示:
2 <= S.length <= 10^5
S
由小写英文字母组成。
1 class Solution { 2 func longestDupSubstring(_ S: String) -> String { 3 var sa:[Int] = suffixArray(Array(S), 26) 4 let n:Int = S.count 5 var lcp:[Int] = buildLCP(Array(S), sa) 6 var isa:[Int] = [Int](repeating:0,count:n) 7 for i in 0..<n {isa[sa[i]] = i} 8 var max:Int = 0 9 var arg:Int = -1 10 for i in 1..<n 11 { 12 if lcp[i] > max 13 { 14 max = lcp[i] 15 arg = i 16 } 17 } 18 if arg == -1 {return String()} 19 return S.subString(sa[arg], max + 1) 20 } 21 22 func buildLCP(_ str:[Character],_ sa:[Int]) -> [Int] 23 { 24 let n:Int = str.count 25 var h:Int = 0 26 var lcp:[Int] = [Int](repeating:0,count:n) 27 var isa:[Int] = [Int](repeating:0,count:n) 28 for i in 0..<n {isa[sa[i]] = i} 29 for i in 0..<n 30 { 31 if isa[i] > 0 32 { 33 let j:Int = sa[isa[i] - 1] 34 while(j+h < n && i+h < n && str[j+h] == str[i+h]) 35 { 36 lcp[isa[i]] = h 37 h += 1 38 } 39 } 40 else 41 { 42 lcp[isa[i]] = 0 43 } 44 if h > 0 {h -= 1} 45 } 46 return lcp 47 } 48 49 func suffixArray(_ str:[Character],_ W:Int) -> [Int] 50 { 51 let n:Int = str.count 52 if n <= 1 {return [Int](repeating:0,count:n)} 53 var sa:[Int] = [Int](repeating:0,count:n) 54 var s:[Int] = [Int](repeating:0,count:n + 3) 55 for i in 0..<n 56 { 57 s[i] = str[i].ascii - 96 58 } 59 suffixArray(s, &sa, n, W+1) 60 return sa 61 } 62 63 func suffixArray(_ s:[Int],_ sa:inout [Int],_ n:Int,_ K:Int) 64 { 65 let n0:Int = (n+2)/3 66 let n1:Int = (n+1)/3 67 let n2:Int = n/3 68 let n02:Int = n0 + n2 69 70 var s12:[Int] = [Int](repeating:0,count:n02 + 3) 71 var sa12:[Int] = [Int](repeating:0,count:n02 + 3) 72 var s0:[Int] = [Int](repeating:0,count:n0) 73 var sa0:[Int] = [Int](repeating:0,count:n0) 74 75 // generate positions of mod 1 and mod 2 suffixes 76 // the "+(n0-n1)" adds a dummy mod 1 suffix if n%3 == 1 77 let sup:Int = n + (n0 - n1) 78 var i1:Int = 0 79 var j1:Int = 0 80 while(i1 < sup) 81 { 82 if i1 + 1 < sup { 83 s12[j1] = i1 + 1 84 j1 += 1 85 } 86 if i1 + 2 < sup { 87 s12[j1] = i1 + 2 88 j1 += 1 89 } 90 i1 += 3 91 } 92 93 // lsb radix sort the mod 1 and mod 2 triples 94 radixPass(s12, &sa12, s, 2, n02, K) 95 radixPass(sa12, &s12, s, 1, n02, K) 96 radixPass(s12, &sa12, s, 0, n02, K) 97 98 // find lexicographic names of triples 99 var name:Int = 0 100 var c0:Int = -1 101 var c1:Int = -1 102 var c2:Int = -1 103 104 for i in 0..<n02 105 { 106 if s[sa12[i]] != c0 || s[sa12[i]+1] != c1 || s[sa12[i]+2] != c2 107 { 108 name += 1 109 c0 = s[sa12[i]] 110 c1 = s[sa12[i]+1] 111 c2 = s[sa12[i]+2] 112 } 113 if sa12[i] % 3 == 1 114 { 115 // left half 116 s12[sa12[i]/3] = name 117 } 118 else 119 { 120 // right half 121 s12[sa12[i]/3 + n0] = name 122 } 123 } 124 125 // recurse if names are not yet unique 126 if name < n02 127 { 128 suffixArray(s12, &sa12, n02, name) 129 // store unique names in s12 using the suffix array 130 for i in 0..<n02 131 { 132 s12[sa12[i]] = i + 1 133 } 134 } 135 else 136 { 137 // generate the suffix array of s12 directly 138 for i in 0..<n02 139 { 140 sa12[s12[i]-1] = i 141 } 142 } 143 144 // stably sort the mod 0 suffixes from sa12 by their first character 145 var i2:Int = 0 146 var j2:Int = 0 147 while(i2 < n02) 148 { 149 if sa12[i2] < n0 150 { 151 s0[j2] = 3 * sa12[i2] 152 j2 += 1 153 } 154 i2 += 1 155 } 156 radixPass(s0, &sa0, s, 0, n0, K) 157 158 // merge sorted sa0 suffixes and sorted sa12 suffixes 159 var p:Int = 0 160 var t:Int = n0 - n1 161 var k:Int = 0 162 while(k < n) 163 { 164 // pos of current offset 12 suffix 165 let i:Int = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2 166 // pos of current offset 0 suffix 167 let j:Int = sa0[p] 168 if sa12[t] < n0 ? 169 (s[i] < s[j] || s[i] == s[j] && s12[sa12[t]+n0] <= s12[j/3]) : 170 (s[i] < s[j] || s[i] == s[j] && (s[i+1] < s[j+1] || s[i+1] == s[j+1] && s12[sa12[t]-n0+1] <= s12[j/3+n0])) 171 { 172 // suffix from a12 is smaller 173 sa[k] = i 174 t += 1 175 if t == n02 176 { 177 // done --- only sa0 suffixes left 178 k += 1 179 while(p < n0) 180 { 181 sa[k] = sa0[p] 182 p += 1 183 k += 1 184 } 185 } 186 } 187 else 188 { 189 // suffix from sa0 is smaller 190 sa[k] = j 191 p += 1 192 if p == n0 193 { 194 // done --- only sa12 suffixes left 195 k += 1 196 while(t < n02) 197 { 198 sa[k] = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2 199 t += 1 200 k += 1 201 } 202 } 203 } 204 k += 1 205 } 206 } 207 208 func radixPass(_ a:[Int],_ b:inout [Int],_ r:[Int],_ l:Int,_ n:Int,_ K:Int) 209 { 210 // counter array 211 var c:[Int] = [Int](repeating:0,count:K + 1) 212 for i in 0..<n 213 { 214 // count occurrences 215 c[r[l + a[i]]] += 1 216 } 217 var i:Int = 0 218 var sum:Int = 0 219 while(i <= K) 220 { 221 // exclusive prefix sums 222 let t:Int = c[i] 223 c[i] = sum 224 sum += t 225 i += 1 226 } 227 for i in 0..<n 228 { 229 b[c[r[l + a[i]]]] = a[i] 230 c[r[l + a[i]]] += 1 231 } 232 } 233 } 234 235 //Character扩展 236 extension Character 237 { 238 //Character转ASCII整数值(定义小写为整数值) 239 var ascii: Int { 240 get { 241 return Int(self.unicodeScalars.first?.value ?? 0) 242 } 243 } 244 } 245 246 extension String { 247 // 截取字符串:指定索引和字符数 248 // - begin: 开始截取处索引 249 // - count: 截取的字符数量 250 func subString(_ begin:Int,_ count:Int) -> String { 251 let start = self.index(self.startIndex, offsetBy: max(0, begin)) 252 let end = self.index(self.startIndex, offsetBy: min(self.count, begin + count)) 253 return String(self[start..<end]) 254 } 255 }
转载于:https://www.cnblogs.com/strengthen/p/10852170.html
[Swift]LeetCode1044. 最长重复子串 | Longest Duplicate Substring相关推荐
- 最长重复子串和最长不重复子串求解
最长重复子串和最长不重复子串求解 本文内容框架: §1 最长重复子串 基本方法.KMP算法求解.后缀数组求解 §2 最长不重复子串 基本方法.动态规划.动态规划+Hash §3 小结 §1最长重复子串 ...
- 动态规划与最长重复子串 LRS and Dynamic Programming
目录 最长重复子串问题 暴力遍历 动态规划 LRS问题中dp数组的意义 重叠问题 暴力遍历 dp解法 一些想法 动态规划和哈希表? s.substr()的时间复杂度? 碎碎念 最长重复子串问题 假设我 ...
- [译+改]最长回文子串(Longest Palindromic Substring) Part II
[译+改]最长回文子串(Longest Palindromic Substring) Part II 原文链接在http://leetcode.com/2011/11/longest-palindro ...
- 最长重复子串(Rabin-Karp算法)
目录 最长重复子串 C++代码 最长重复子串 1044. 最长重复子串 给出一个字符串 S,考虑其所有重复子串(S 的连续子串,出现两次或多次,可能会有重叠). 返回任何具有最长可能长度的重复子串.( ...
- 后缀数组求最长重复子串
问题描述 给定一个字符串,求出其最长重复子串 例如:abcdabcd 最长重复子串是 abcd,最长重复子串可以重叠 例如:abcdabcda,这时最长重复子串是 abcda,中间的 a 是被重叠的. ...
- #1407 : 后缀数组二·重复旋律2 (不可重叠最长重复子串问题)
题目链接 思路 求不可重叠最长重复子串,也可以利用height[i]height[i]height[i]. 二分枚举答案KKK 当height[i]≥Kheight[i] \ge Kheight[i] ...
- 后缀数组--(可重叠最长重复子串问题)
问题描述:给定一个字符串,求最长重复子串,这两个子串可以重叠. 其实问题可以转化为height数组的最大值.至于为什么是这样,我可以这样解释: 求可重叠最长重复子串等价于求两个后缀的最长公共前缀的最大 ...
- 牛客题霸 [最长重复子串] C++题解/答案
牛客题霸 [最长重复子串] C++题解/答案 题目描述 一个重复字符串是由两个相同的字符串首尾拼接而成,例如abcabc便是长度为6的一个重复字符串,而abcba则不存在重复字符串. 给定一个字符串, ...
- 最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和...
最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和 文章作者:Yx.Ac 文章来源:勇幸|Thinking (http://www.ahathi ...
最新文章
- HDLBits 系列(39)求解带有奇校验的串口接收数据的简化电路设计
- CoordinatorLayout+AppBarLayout实现上滑隐藏ToolBar-Android M新控件
- Apache Kafka 不需要管理员:删除 Apache ZooKeeper 的依赖
- 如何用python做数据分析统计服_使用python实现数据分析
- 关闭或修改 IIS 443 端口
- 【perl脚本】单行循环正则匹配
- 高中数学:抛物线专题讲解利用韦达定理求解技巧
- 森林中的兔子java
- 网盘翻车不断,我是如何低价自建一个自用网盘
- 下载源码报错Cannot connect to the Maven process. Try again later. If the problem persists, check the Maven
- 深度学习入门笔记(十六):计算机视觉之边缘检测
- 点卯.三维视频融合助力国家全面推进实景三维中国建设, 构建数字中国建设基座 ;开放C++源代码 点卯-魔镜系列
- 音游手台中--EC11编码器的控制[2]
- QAT量化感知训练(一)【详解】
- 第6期(江西省吉安市永丰县)县长手机信箱工作简报(自吹自擂政绩,自圆其说)
- 2022年密码测评理论与关键技术前沿论坛|海泰方圆分享密码应用改造典型方案
- android手机 垃圾箱,Dumpster Pro「回收站」v3.6.386 for Android 直装解锁高级版 —— 一款不错的 Android 垃圾箱 / 回收站应用...
- 《C算法.第1卷,基础、数据结构、排序和搜索(第三版)》电子书下载 -(百度网盘 高清版PDF格式)
- 【RocketMQ】消息的高可用与负载均衡
- 一个典型程序员的IT 7年
热门文章
- 代码优化四部曲:“拆套”、“解耦”、”封装“、“重构”
- [C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别(日文翻译)...
- 【刘晓燕语法长难句】 并列句
- 【区块链】区块链是什么?
- Powershell有哪些用途
- PowerShell监控——监控电脑屏幕操作记录
- Linux操作Oracle(16)——Oracle扩容报错:ORA-01144_表空间数据文件超出最大限制
- SELinux系列(一)——SELinux是什么
- csharp与java的区别_C#与JAVA之比较(1)
- 实验9Linux共享内存通信,操作系统原理与Linux实践教程(卓越工程师培养计划系列教材)...