相似字符串组
如果交换字符串 X 中的两个不同位置的字母,使得它和字符串 Y 相等,那么称 X 和 Y 两个字符串相似。如果这两个字符串本身是相等的,那它们也是相似的。
例如,“tars” 和 “rats” 是相似的 (交换 0 与 2 的位置); “rats” 和 “arts” 也是相似的,但是 “star” 不与 “tars”,“rats”,或 “arts” 相似。
总之,它们通过相似性形成了两个关联组:{“tars”, “rats”, “arts”} 和 {“star”}。注意,“tars” 和 “arts” 是在同一组中,即使它们并不相似。形式上,对每个组而言,要确定一个单词在组中,只需要这个词和该组中至少一个单词相似。
给你一个字符串列表 strs。列表中的每个字符串都是 strs 中其它所有字符串的一个字母异位词。请问 strs 中有多少个相似字符串组?
示例 1:
输入:strs = [“tars”,“rats”,“arts”,“star”]
输出:2
示例 2:
输入:strs = [“omv”,“ovm”]
输出:1
提示:
1 <= strs.length <= 300
1 <= strs[i].length <= 300
strs[i] 只包含小写字母。
strs 中的所有单词都具有相同的长度,且是彼此的字母异位词。
思想:首先设一个临时数组保存每个字符串所属的集合,取第i个字符串将它和第j个字符串比较(i<j),若这两个字符串仅有两个位置不一样且交换这两个字符两字符串相等则把这两个字符串归为一个集合,若另一个字符串和该集合中的任意一个具有以上特点则将它也归为这个集合,一开始初始化让每个字符串等于各自的下标。至于如何判断交换后是否相等,可以在比较的时候记录两个不一样的下标x,y,字符串i的x位置和字符串j的y位置的元素相同则表示交换后相同。注意在归属集合时不能只该当前字符串而是要把该集合的所有字符串的归属都改了。遍历所以的字符串即可得到结果。
#include<iostream>
#include<string>
using namespace std;
int numSimilarGroup(string a[],int n);
int main()
{
string a[]={"kccomwcgcs","socgcmcwkc","sgckwcmcoc","coswcmcgkc","cowkccmsgc","cosgmccwkc","sgmkwcccoc","coswmccgkc","kowcccmsgc","kgcomwcccs"};
cout << numSimilarGroup(a,10)<<endl;
return 0;
}
int numSimilarGroup(string a[],int n)
{
int sn=a[0].size();
int sum=0;
int* t = new int[n];
for (int i = 0; i < n; i++)
{
t[i] = i;
}
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
int c=0,x=0,y=0;
for(int k=0;k<sn;k++)
{
if(a[i][k]!=a[j][k])
{
c++;
if(c<2)
x=k;
else
y=k;
}
}
if(c==2)
{
if(a[i][x]==a[j][y])
{
int nk = t[j];
for (int mk = 0; mk < n;mk++)
{
if(t[mk]==nk)
t[mk] = t[i];
}
}
}
else if(c==0)
{
int nk = t[j];
for (int mk = 0; mk < n;mk++)
{
if(t[mk]==nk)
t[mk] = t[i];
}
}
}
for (int i = 0; i < n; i++)
{
if(t[i]==i)
sum++;
}
return sum;
}