title
给你一个字符串数组 ideas 表示在公司命名过程中使用的名字列表。公司命名流程如下:
- 从
ideas中选择 2 个 不同 名字,称为ideaA和ideaB。 - 交换
ideaA和ideaB的首字母。 - 如果得到的两个新名字 都 不在
ideas中,那么ideaA ideaB(串联ideaA和ideaB,中间用一个空格分隔)是一个有效的公司名字。 - 否则,不是一个有效的名字。
返回 不同 且有效的公司名字的数目。
示例 1:
输入:ideas = ["coffee","donuts","time","toffee"]
输出:6
解释:下面列出一些有效的选择方案:
- ("coffee", "donuts"):对应的公司名字是 "doffee conuts" 。
- ("donuts", "coffee"):对应的公司名字是 "conuts doffee" 。
- ("donuts", "time"):对应的公司名字是 "tonuts dime" 。
- ("donuts", "toffee"):对应的公司名字是 "tonuts doffee" 。
- ("time", "donuts"):对应的公司名字是 "dime tonuts" 。
- ("toffee", "donuts"):对应的公司名字是 "doffee tonuts" 。
因此,总共有 6 个不同的公司名字。
下面列出一些无效的选择方案:
- ("coffee", "time"):在原数组中存在交换后形成的名字 "toffee" 。
- ("time", "toffee"):在原数组中存在交换后形成的两个名字。
- ("coffee", "toffee"):在原数组中存在交换后形成的两个名字。
示例 2:
输入:ideas = ["lack","back"]
输出:0
解释:不存在有效的选择方案。因此,返回 0 。
提示:
2 <= ideas.length <= 5 * 1041 <= ideas[i].length <= 10ideas[i]由小写英文字母组成ideas中的所有字符串 互不相同
solution
统计任选两个元素,交换首元素后的不同数量。
首字母 数量<=26, 这是关键点。
枚举首字母 和 ideas元素,这样两个首字母和第一个元素的后缀就知道了。待确定第二个元素的后缀。可以先行计算更换首字母c -> a的这样数量,结果就是+这个值。

class Solution:
def distinctNames(self, ideas: List[str]) -> int:
ideas = set(ideas)
cnt = [[0] * 26 for _ in range(26)]
for s in ideas:
a, b = s[0], s[1:]
for i in range(26):
c = chr(97 + i)
if c + b not in ideas:
cnt[ord(a) - 97][i] += 1
ans = 0
for i in range(26):
c = chr(97 + i)
for s in ideas:
a, b = s[0], s[1:]
if c + b not in ideas:
ans += cnt[i][ord(a) - 97]
return ans