計蒜客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<cstdio>
#include<iostream>
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章