题解 CF975A 【Aramic script】

· · 题解

Content

定义一个字符串的根为字符串中不同种类的字符按字典序非降序排列得到的字符串。例如 \texttt{aaa} 的词根为 \texttt{a}\texttt{babb} 的词根为 \texttt{ab}\texttt{abczfee} 的词根为 \texttt{abcefz},等等。

现在给出 n 个字符串,求不同的根的个数。

数据范围:1\leqslant n\leqslant 10^3,字符串长度不超过 10^3

Solution

我们看完题之后分析一下就明白,这道题目主要是三个操作:

  1. 字符串的每个字符按照字典序非降序排列。
  2. 将重复的字符去掉。
  3. 判断是否已经出现过。

那我们将每个操作依次分析一下吧。首先是第一个操作,这里教大家用一个非常好用的技巧——用 \texttt{sort} 直接排序。你没听错,\texttt{sort} 就是强大到可以直接将第一个操作一刀切。我们假设现在的字符串为 s,然后我们可以通过调用 \texttt{sort(s.begin(), s.end());}(其实也就相当于将字符串彻头彻尾地按照字典序非降序排列)就可以得到一个里面所有的字符都是按照字典序非降序排列的字符串了。

然后是第二个操作,排序完之后,我们直接遍历字符串,如果当前扫到的字符不和前面的字符相等就加到这个字符串的根里面去,直到扫完为止,这时我们就可以得到一个字符串的根了。

最后是第三个操作,我们可以开一个 \texttt{map} 来直接将字符串是否出现映射到一个变量上去,这样就可以直接判断字符串的根是否出现过,不需要再用 \texttt{hash} 判断了。

## Code ```cpp int n, ans; string s; map<string, int> vis; int main() { getint(n); while(n--) { cin >> s; string root = ""; sort(s.begin(), s.end()); int len = s.size(); _for(i, 0, len - 1) if(s[i] != s[i - 1]) root += s[i]; if(!vis[root]) {ans++, vis[root] = 1;} } writeint(ans); return 0; } ```