最长连续回文串Swift实现

题目:Longest Palindromic Substring

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.

Example:

Input: "cbbd"

Output: "bb"

算法分析

解法一:

暴力解法,时间复杂度:O(n^n)。

遍历每一个字符,然后左右依次向两边比较是否相等,继而判断是否满足回文串的条件,找出最长即可。注意需要判断回文长度为奇,偶长度的情况。

解法二:

  • 动态规划,时间复杂度:O(n^2)。
    dp[i][j] 表示从i~j的子串是否是回文串。

动态转移方程:

dp[i][j] = {
    dp[i-1][j + 1] : s[i] == s[j],
    false          : s[i] != s[j]
}

Swift实现

class Solution {
    func longestPalindrome(_ s: String) -> String {
        var dp:[[Bool]] = [];
        if s.count <= 1{
            return s;
        }
        
        var longest:Int = 1;
        var left:Int = 0;
        var right:Int = 0;
        
        for var i in 0...s.count - 1{
            var eachRow:[Bool] = [];
            for var j in 0...s.count - 1{
                if i == j{
                    eachRow.append(true);
                }else{
                    eachRow.append(false);
                }
            }
            dp.append(eachRow);
        }
        
        var i:Int = 0;
        var j:Int = 0;
        for var character_j in s {
            if j == 0 {
                j += 1;
                continue;
            }
            i = 0;
            for var character_i in s {
                if character_i == character_j {
                    dp[i][j] = dp[i + 1][j - 1] || j - i <= 1;
                    if dp[i][j] && j - i + 1 > longest{
                        longest = j - i + 1;
                        left = i;
                        right = j;
                    }
                }else{
                    dp[i][j] = false;
                }
                i += 1;
                if i >= j{
                    break;
                }
            }
            j += 1;
        }
        let leftIndex = s.index(s.startIndex, offsetBy: left);
        let rightIndex = s.index(s.startIndex, offsetBy: right);
        return String(s[leftIndex...rightIndex]);
    }
}

AC结果:可能是swift处理字符串的效率问题会超时。

Time Limit Exceeded

第三种解法

  • Manacher算法,时间复杂度:O(n)。

Manacher's ALGORITHM: O(n)时间求字符串的最长回文子串思路分析这里介绍的很清晰,
此处只是简单介绍与Swift实现。

首先解决回文长度为奇偶的问题

  • 插桩处理,整个字符串的前后间隔处插入'#'字符,最终得到的字符串就一定是奇数长度,回文的长度也一定是奇数长度。

我们来举一个例子:"cbbd"。先进行插桩处理 -> "#c#b#b#d#"。我们定义一个数组P[i]用来记录以i处的字符作为轴心的最大的回文半径。我们自己计算得到如下的对应关系:

# c # b # b # d #
1 2 1 2 3 2 1 2 1

解决计算P[i]问题

我们增加两个辅助量id,max分别代表当前计算的到最右边回文覆盖的轴心与最右下标。借用Manacher's ALGORITHM: O(n)时间求字符串的最长回文子串中的两张图解:

当 mx - i > P[j] 的时候,以S[j]为中心的回文子串包含在以S[id]为中心的回文子串中,由于 i 和 j 对称,以S[i]为中心的回文子串必然包含在以S[id]为中心的回文子串中,所以必有 P[i] = P[j],见下图。

Longest Palindromic Substring_1.png

当 P[j] >= mx - i 的时候,以S[j]为中心的回文子串不一定完全包含于以S[id]为中心的回文子串中,但是基于对称性可知,下图中两个绿框所包围的部分是相同的,也就是说以S[i]为中心的回文子串,其向右至少会扩张到mx的位置,也就是说 P[i] >= mx - i。至于mx之后的部分是否对称,就只能老老实实去匹配了。


Longest Palindromic Substring_2.png

得到的计算的方程式:

//记j = 2 * id - i,也就是说 j 是 i 关于 id 的对称点(j = id - (i - id))
P[i] = {
    P[j] ,mx - i > P[j]
    mx - i, mx - i <= P[j]
}

Swift 实现

class Solution {
    func longestPalindrome(_ s: String) -> String {
        if s.count <= 1 {
            return s;
        }
    
        // 1.间隔之间先插入#
        var newString:String = "#";
        for var character in s {
            newString.append(character);
            newString = newString + "#";
        }
        let characters = Array(newString);
        
        // 2.遍历找出以每个节点作为轴最长半径
        var maxId:Int = 0;
        var max:Int = 0;
        var ids:[Int] = [];
        ids.append(1);
        var maxLength:Int = 1;
        var maxLengthIndex = 0;
        
        for var i in 1...characters.count - 1 {
            var j:Int = maxId - (i - maxId);
            if max > i && j >= 0 {
                ids.append(min(ids[j], max - i));
            }else{
                ids.append(1);
            }
            while i + ids[i] <= characters.count - 1 && i - ids[i] >= 0 && characters[i + ids[i]] == characters[i - ids[i]]{
                ids[i] += 1;
            }
            
            if i + ids[i] - 1 > max {
                maxId = i;
                max = i + ids[i] - 1;
            }
            
            if ids[i] > maxLength{
                maxLength = ids[i];
                maxLengthIndex = i;
            }
        }
        let leftIndex = s.index(s.startIndex, offsetBy: (maxLengthIndex - (maxLength - 1))/2);
        let rightIndex = s.index(leftIndex, offsetBy:maxLength - 1 - 1);
        return String(s[leftIndex...rightIndex]);
    }
}

AC结果:

Accepted

参考

https://www.felix021.com/blog/read.php?2040

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • “你身体还好吗?昨天梦见你回来了。”刚睡醒,妈妈打来电话。 其实,距离离开家,还不到一周。 突然感觉很感伤,明白自...
    木萧鸣阅读 237评论 1 1
  • “主人,五一到了你准备去哪玩啊?”电话那头传来包奕凡的声音。“睡觉啊,这几天累死了。”“那可不行,我好不容易才...
    LT_Tamia_92e5阅读 442评论 0 0
  • 1、依据官方文档进行如下配置: 2、在build的时候可能会报依赖包冲突异常,在build.gradle中添加如下...
    紫苓阅读 755评论 0 1
  • 一个人对你好不好, 取决于你在他心里重不重要。 看重你,给你的都是踏实依靠; 看轻你,给你的都是虚无缥缈。 一颗心...
    漂浮的流云阅读 330评论 2 3