[Leetcode] 555. Split Concatenated Strings 解题报告

给定一组字符串,需要找到最佳的拼接方式和切割点,使得形成的普通字符串字典序最大。策略是首先使所有字符串字典序最大化,然后遍历并尝试在每个位置切割,找到字典序最大的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

Given a list of strings, you could concatenate these strings together into a loop, where for each string you could choose to reverse it or not. Among all the possible loops, you need to find the lexicographically biggest string after cutting the loop, which will make the looped string into a regular one.

Specifically, to find the lexicographically biggest string, you need to experience two phases:

  1. Concatenate all the strings into a loop, where you can reverse some strings or not and connect them in the same order as given.
  2. Cut and make one breakpoint in any place of the loop, which will make the looped string into a regular one starting from the character at the cutpoint.

And your job is to find the lexicographically biggest one among all the possible regular strings.

Example:

Input: "abc", "xyz"
Output: "zyxcba"
Explanation: You can get the looped string "-abcxyz-", "-abczyx-", "-cbaxyz-", "-cbazyx-", 
where '-' represents the looped status.
The answer string came from the fourth looped one,
where you could cut from the middle character 'a' and get "zyxcba".

Note:

  1. The input strings will only contain lowercase letters.
  2. The total length of all the strings will not over 1,000.

思路

最终的regular result一定是从某个string a的某个地方切开的(包括在string[0]之前切开)。那么其余string是否需要reverse则取决于reverse之后其字典序是否会增大,如果增大了就reverse,否则就保持原貌,因为只有这样才能保证最后的结果是字典序最大的。而对于a而言,是否需要反向,以及从哪里切开,均取决于最终形成的字符串头部的字典序大小。

所以我们的解法就是:首先将所有的字符串都处理成字典序最大的(反向或者不反向),然后连接起来。接着遍历每个字符串,试图将它以及它的reverse从每个位置切开,并测试形成的regular字符串,一旦发现其字典序大于当前的最大值,则更新当前最大值。最后返回最大值即可。

注意我们在下面的代码片段中,首先将res初始化为“a”,即为字典序中最小的字符串。而在测试切开位置的过程中,只有在p1[j]或者p2[j]大于res[0]的时候才更新res,这样就可以减少冗余的字符串拼接操作,从而提高运行效率。

代码

class Solution {
public:
    string splitLoopedString(vector<string>& strs) {
        string s = "", res = "a";   // res is initialized as the smallest one
        for (int i = 0; i < strs.size(); ++i) {
            string r = strs[i];
            reverse(r.begin(), r.end());
            s += max(r, strs[i]);   // s is the concantenated with the biggest words
        }
        for (int i = 0, st = 0; i < strs.size(); st += strs[i++].size()) {
            string p1 = strs[i], p2 = strs[i];
            reverse(p2.begin(), p2.end());
            string body = s.substr(st + p1.size()) + s.substr(0, st);  // the body that do not contain strs[i]
            for (auto j = 0; j < strs[i].size(); ++j) {
                // do not check the cutting point if the first letter is smaller
                // than the first letter of the current best result.
                if (p1[j] >= res[0]) {  
                    res = max(res, p1.substr(j) + body + p1.substr(0, j));
                }
                if (p2[j] >= res[0]) {
                    res = max(res, p2.substr(j) + body + p2.substr(0, j));
                }
            }
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值