• [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:

    1. 2 <= S.length <= 10^5
    2. S consists of lowercase English letters.

    给出一个字符串 S,考虑其所有重复子串(S 的连续子串,出现两次或多次,可能会有重叠)。

    返回任何具有最长可能长度的重复子串。(如果 S 不含重复子串,那么答案为 ""。)

    示例 1:

    输入:"banana"
    输出:"ana"
    

    示例 2:

    输入:"abcd"
    输出:""

    提示:

    1. 2 <= S.length <= 10^5
    2. S 由小写英文字母组成。

    Runtime: 356 ms
    Memory Usage: 27.3 MB
      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 }
  • 相关阅读:
    突破
    leetcode刷题 538~
    leetcode刷题 519~
    Docker练习之镜像更新方法1
    十二 Linux之tar解压缩
    十一 Linux软件包管理yum
    十 Linux指令之grep
    九 linux指令之find
    八 Linux ps指令查看进程和kill杀进程
    七 Linux top命令
  • 原文地址:https://www.cnblogs.com/strengthen/p/10852170.html
Copyright © 2020-2023  润新知