字符串排序

[牛客链接](https://www.nowcoder.com/practice/9ad2f07d6eb74a6e935e54279b29910d)

思路

本题要求按自定义字母顺序对字符串进行字典序排序。

输入的第一行是一个包含 26 个不同小写字母的字符串,它定义了字母的大小关系:排在前面的字母"更小"。例如 zyxwvutsrqponmlkjihgfedcba 表示 z 最小、a 最大。

排序规则和标准字典序完全一致,只是字母的大小关系由输入决定:

  • 逐字符比较,遇到不同字符时,按自定义顺序判断大小。
  • 若一个字符串是另一个的前缀,则较短的排在前面。

做法: 用一个数组 rank[c] 记录每个字母 c 在自定义顺序中的位置(越小排越前),然后在比较函数中用 rank 值替代原始字符值即可。排序直接使用语言自带的排序函数。

以样例 2 为例:

自定义顺序 zyxwvutsrqponmlkjihgfedcba,其中 c 的位置是 23,a 的位置是 25。比较 aacaaa:前两个字符相同,第三个字符 c(rank 23)< a(rank 25),所以 aac 排在 aaa 前面。aaaaaaa 为前缀且更长,排在 aaa 后面。最终结果:aac, aaa, aaaa

复杂度

  • 时间复杂度:,其中 是字符串数量, 是字符串平均长度。排序 次比较,每次比较
  • 空间复杂度:,存储所有字符串。

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string order;
    cin >> order;

    int rank[26];
    for (int i = 0; i < 26; i++) {
        rank[order[i] - 'a'] = i;
    }

    int n;
    cin >> n;

    vector<string> strs(n);
    for (int i = 0; i < n; i++) {
        cin >> strs[i];
    }

    sort(strs.begin(), strs.end(), [&](const string& a, const string& b) {
        int len = min(a.size(), b.size());
        for (int i = 0; i < len; i++) {
            if (a[i] != b[i]) {
                return rank[a[i] - 'a'] < rank[b[i] - 'a'];
            }
        }
        return a.size() < b.size();
    });

    for (int i = 0; i < n; i++) {
        cout << strs[i] << '\n';
    }

    return 0;
}
import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String order = br.readLine().trim();

        int[] rank = new int[26];
        for (int i = 0; i < 26; i++) {
            rank[order.charAt(i) - 'a'] = i;
        }

        int n = Integer.parseInt(br.readLine().trim());
        String[] strs = new String[n];
        for (int i = 0; i < n; i++) {
            strs[i] = br.readLine().trim();
        }

        Arrays.sort(strs, (a, b) -> {
            int len = Math.min(a.length(), b.length());
            for (int i = 0; i < len; i++) {
                if (a.charAt(i) != b.charAt(i)) {
                    return rank[a.charAt(i) - 'a'] - rank[b.charAt(i) - 'a'];
                }
            }
            return a.length() - b.length();
        });

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            sb.append(strs[i]).append('\n');
        }
        System.out.print(sb);
    }
}