描述
定义一个由小写字母构成的字符串 s 的“兄弟单词”为:任意交换 s 中两个字母的位置,得到的新字符串,且其与 s 不同。
现在,对于给定的 n 个字符串 s1,s2,…,sn 和另一个单独的字符串 x ,你需要解决两个问题:
∙统计这 n 个字符串中,有多少个是 x 的“兄弟单词”;
∙将这 n 个字符串中 x 的“兄弟单词”按字典序从小到大排序,输出排序后的第 k 个兄弟单词。特别地,如果不存在,则不输出任何内容。
从字符串的第一个字符开始逐个比较,直到找到第一个不同的位置,通过比较这个位置字符的字母表顺序得出字符串的大小,称为字典序比较。
输入描述:
在一行上:
1.先输入一个整数 n(1≦n≦1000) 代表字符串的个数;
2.随后,输入 n 个长度为 1≦length(si)≦10 ,仅由小写字母构成的字符串 s1,s2,…,sn ;
3.随后,输入一个字符串 x ;
4.最后,输入一个整数 k(1≦k≦n) 代表要查找的兄弟单词的序号。
输出描述:
第一行输出一个整数,代表给定的 n 个字符串中,x 的“兄弟单词”的数量;
第二行输出一个字符串,代表将给定的 n 个字符串中 x 的“兄弟单词”按字典序排序后的第 k 小兄弟单词。特别地,如果不存在,则不输出任何内容。
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// 判断两个字符串是否是兄弟字符串
const isBro = (s, k) => {
if (s.length < 2) return false;
if (s.length !== k.length) return false;
if (s === k) return false;
const sMap = new Map();
const kMap = new Map();
// 统计字符频率
for (let i = 0; i < s.length; i++) {
sMap.set(s[i], (sMap.get(s[i]) || 0) + 1);
kMap.set(k[i], (kMap.get(k[i]) || 0) + 1);
}
// 比较两个 Map 的内容是否相同
if (sMap.size !== kMap.size) return false;
for (let [key, value] of sMap) {
if (kMap.get(key) !== value) return false;
}
return true;
};
while ((line = await readline())) {
let tokens = line.split(" ");
const broArr = tokens.slice(0, -2); // 提取所有候选兄弟字符串
const s = tokens[tokens.length - 2]; // 目标单词
const num = parseInt(tokens[tokens.length - 1], 10); // 指定的序号
// 使用 filter 方法收集兄弟字符串
const arr = broArr.filter((word) => isBro(s, word));
// 输出兄弟字符串的数量
console.log(arr.length);
// 如果存在兄弟字符串且序号有效,输出第 n 个兄弟字符串
if (arr.length >= num) {
arr.sort((a, b) => a.localeCompare(b)); // 按字典序排序
console.log(arr[num - 1]);
}
}
})();