题目描述:
小 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;
}