计蒜客T3106-小B的魔法-并查集

题目描述:

小 B 表演魔法。

观众给他两个 字符串 S,T,这两个字符串中只包含 小写 字母。

现在小 B 可以把两个字符串中任意所有的字母 x 替换成 y( x,y 代表任意字母),记为一次魔法操作。

注:任意所有指的是任何一种字母,它在两个串中的所有出现的位置都可以替换成同一种字母,当然也可以替换它们中的几个。

观众想知道,将两个字符串变为全等的最少操作次数是多少?

小 B 只会变魔术,所以他想让你求出这个次数。

注:全等指对于任意的 1≤i≤n,都有 S[i]=T[i]。 (字符串坐标从 1 开始)

输入描述:

第一行一个整数 n,表示字符串的长度。

接下来的两行,每行一个长度为 n 的字符串,即 S 和 T。

对于 30% 的数据,1≤n≤10。

对于 70% 的数据,1≤n≤103

对于 100% 的数据,1≤n≤105

输出描述:

一行一个整数,表示最少的操作次数。

输入样例:

3
aab
zcb

输出样例:

2

核心思想:

并查集。26个字母,初始祖先均为自己。
对于1≤i≤n,如果s[i]!=t[i],则将两者并在一起,ans++。

代码如下:

#include
#include
using namespace std;
typedef long long ll;
const int N=1e5+20,M=32;
int pre[M],num[M];
char s[N],t[N];
int find(int x)
{
	if(pre[x]==x)
		return x;
	return pre[x]=find(pre[x]);
}
int merge(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if(fx==fy) return 0;
	if(num[fx]>num[fy])
	{
		pre[fy]=fx;
		num[fx]+=num[fy];
	}
	else
	{
		pre[fx]=fy;
		num[fy]+=num[fx];
	}
	return 1;
}
int main()
{
	int n,ans=0;
	cin>>n;
	scanf("%s%s",s,t);
	for(int i=0;i<M;i++)
	{
		pre[i]=i;
		num[i]=1;
	}
	for(int i=0;i<n;i++)
	{
		int x=s[i]-'a';
		int y=t[i]-'a';
		ans+=merge(x,y);
	}
	cout<<ans<<endl;
	return 0;
}

你可能感兴趣的:(并查集,字符串)