LC-1616. 分割两个字符串得到回文串(相向双指针、中心扩展)

1616. 分割两个字符串得到回文串

难度中等57

给你两个字符串 ab ,它们长度相同。请你选择一个下标,将两个字符串都在 相同的下标 分割开。由 a 可以得到两个字符串: aprefixasuffix ,满足 a = aprefix + asuffix ,同理,由 b 可以得到两个字符串 bprefixbsuffix ,满足 b = bprefix + bsuffix 。请你判断 aprefix + bsuffix 或者 bprefix + asuffix 能否构成回文串。

当你将一个字符串 s 分割成 sprefixssuffix 时, ssuffix 或者 sprefix 可以为空。比方说, s = "abc" 那么 "" + "abc""a" + "bc" "ab" + "c""abc" + "" 都是合法分割。

如果 能构成回文字符串 ,那么请返回 true,否则返回 false

注意x + y 表示连接字符串 xy

示例 1:

输入:a = "x", b = "y"
输出:true
解释:如果 a 或者 b 是回文串,那么答案一定为 true ,因为你可以如下分割:
aprefix = "", asuffix = "x"
bprefix = "", bsuffix = "y"
那么 aprefix + bsuffix = "" + "y" = "y" 是回文串。

示例 2:

输入:a = "abdef", b = "fecab"
输出:true

示例 3:

输入:a = "ulacfd", b = "jizalu"
输出:true
解释:在下标为 3 处分割:
aprefix = "ula", asuffix = "cfd"
bprefix = "jiz", bsuffix = "alu"
那么 aprefix + bsuffix = "ula" + "alu" = "ulaalu" 是回文串。

提示:

  • 1 <= a.length, b.length <= 105
  • a.length == b.length
  • ab 都只包含小写英文字母

暴力(超时)

class Solution {
    public boolean checkPalindromeFormation(String a, String b) {
        for(int i = 0; i < a.length(); i++){
            if(check(a,b,i)) return true;
        }
        return false;
    }

    public boolean check(String a, String b, int idx){
        String str1 = a.substring(0, idx) + b.substring(idx);
        String str2 = b.substring(0, idx) + a.substring(idx);
        if(isrev(str1) || isrev(str2)) return true;
        else return false;
    }

    public boolean isrev(String s){
        int l = 0, r = s.length()-1;
        while(l < r){
            if(s.charAt(l) != s.charAt(r)) return false;
            l++; r--;
        }
        return true;
    }
}

相向双指针优化

相向双指针求出前后缀最长匹配串, 然后判断a或b中剩余部分是否为回文串

class Solution {
    // apre + bsuf 可以分为两种: 长为m的a前缀 + a\b中间是回文串 + 长为m的b前缀
    // 相向双指针求出前后缀最长匹配串, 然后判断a或b中剩余部分是否为回文串
    public boolean checkPalindromeFormation(String a, String b) {
        return check(a, b) || check(b, a);
    }
    // 如果 a_prefix + b_suffix 可以构成回文串则返回 true,否则返回 false
    public boolean check(String a, String b){
        int i = 0, j = a.length() - 1;
        while(i < j && a.charAt(i) == b.charAt(j)){// 前后缀尽量匹配
            i++; j--;    
        }
        return isPalindrome(a, i, j)|| isPalindrome(b, i, j);
    }
    // 如果从 s[i] 到 s[j] 是回文串则返回 true,否则返回 false
    public boolean isPalindrome(String s, int i, int j){
        while(i < j && s.charAt(i) == s.charAt(j)){
            ++i; --j;
        }
        return i >= j;
    }
}

法二:中心扩展法(题解:Ikaruga)

647. 回文子串

https://leetcode.cn/problems/palindromic-substrings/solution/palindromic-substrings-by-ikaruga/

题解:https://leetcode.cn/problems/split-two-strings-to-make-palindrome/solution/split-two-strings-to-make-palindrome-by-ikaruga/

  1. 题目给出的字符串长度固定,可以直接使用 中心扩展法 检测
    1. 由中心向两侧分别检测字符串 a 和 b
    2. 即【前 a 后 a】和【前 b 后 b】
    3. 不断扩展,直到字符不相同,中间部分都是回文串
    4. 结合下图观看,同时检测两条字符串,我们只关心回文更长的那串,具体是哪条更长不重要
  2. 当不符合回文串时,有一次机会将两个字符串拼接一下
    1. 继续扩展检测,这次检测拼接后的字符串
    2. 即【前 a 后 b】和【前 b 后 a】
    3. 结合下图观看,因为拼接的字符串既有 a 也有 b,所以之前更长的是哪串都不影响
  3. 当再次结束检测时
    1. 如字符再次不相同,则是匹配失败
    2. 如全部匹配,则 left 应该为 -1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hRpXFYYn-1679098921481)(https://pic.leetcode-cn.com/1602390786-XfOHyx-%E5%9B%BE%E7%89%87.png)]

  • 如图所示,第一次检测时,字符串 a 的中心并没有回文串,而字符串 b 有一段合法回文串
  • 第二次检测时,【前 a 后 b】通过测试
  • 最终,【前 a 后 b】和 b 的中心子串组合起来,就是拼接后的回文串(所有有底色的字符)
class Solution {
    public boolean checkPalindromeFormation(String a, String b) {
        int left = a.length()/2 - 1;
        left = Math.min(check(a, a, left), check(b, b, left));
        left = Math.min(check(a, b, left), check(b, a, left));
        return left == -1;
    }

    int check(String str1, String str2, int left){
        int right = str1.length() - 1 - left;
        while(left >= 0 && str1.charAt(left) == str2.charAt(right)){
            left--; right++;
        }
        return left;
    }
}

eft;
while(left >= 0 && str1.charAt(left) == str2.charAt(right)){
left–; right++;
}
return left;
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在LC-3上输出一个字符串,可以使用循环来逐个输出字符串中的字符,直到遇到字符串的终止符号(通常是空字符'\0')。可以使用TRAP指令调用操作系统提供的输出函数PUTC来输出字符。 以下是一个输出字符串的示例程序: ``` ; 输出字符串 LEA R0, MESSAGE ; 将消息字符串的地址加载到R0中 LOOP: LDR R1, R0, #0 ; 从地址R0处读取一个字符到R1中 BRz DONE ; 如果字符为0,则跳转到DONE PUTC ; 输出字符 ADD R0, R0, #1 ; R0加1,指向下一个字符 BR LOOP ; 继续循环输出字符 DONE: RET ; 返回 MESSAGE .STRINGZ "Hello, World!" ; 消息字符串 ``` 要在LC-3上输入一个字符串,可以使用循环来逐个读取输入的字符,直到遇到输入的终止符号(通常是回车符'\r')。可以使用TRAP指令调用操作系统提供的输入函数GETC来读取字符。 以下是一个输入字符串的示例程序: ``` ; 输入字符串 LEA R0, BUFFER ; 将缓冲区的地址加载到R0中 AND R1, R1, #0 ; R1清零,用于记录输入的字符数 LOOP: GETC ; 读取一个字符 OUT ; 将字符输出到控制台 ST R0, R1, #0 ; 将字符存储到缓冲区 ADD R1, R1, #1 ; R1加1,记录输入的字符数 ADD R0, R0, #1 ; R0加1,指向下一个存储位置 BRnzp LOOP ; 如果字符不为0,则继续循环输入 STR R1, R0, #0 ; 将字符数存储到缓冲区的末尾 RET ; 返回 BUFFER .BLKW 80 ; 缓冲区,最多可以存储80个字符 ``` 在这个例子中,我们使用一个缓冲区来存储输入的字符串,并在输入结束后将字符串的长度存储在缓冲区的末尾。要输出和输入字符串,可以将这两个例子结合起来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值