#include <utility>
#include <queue>
#include <type_traits>
#include <cstdlib>
#include <algorithm>
#include <functional>
#include <vector>
#include <string>
#include <limits>
#include <iostream>
namespace lc {
template <class WeightType, class CapacityType>
struct EdgeWithWeightAndCapacity {
	int to;
	WeightType weight;
	CapacityType capacity;
	EdgeWithWeightAndCapacity() : to(0), weight(), capacity() { }
	EdgeWithWeightAndCapacity(
		int to, const WeightType &weight, const CapacityType &capacity)
		: to(to), weight(weight), capacity(capacity)
	{ }
};
}
namespace lc {
template <typename EdgeType>
class AdjacencyList {
public:
	typedef std::vector<EdgeType> ListType;
private:
	std::vector<ListType> m_lists;
public:
	explicit AdjacencyList(int n = 0)
		: m_lists(n)
	{ }
	int size() const { return m_lists.size(); }
	template <typename... Args>
	void add_edge(int u, Args&&... args){
		m_lists[u].emplace_back(args...);
	}
	const ListType &operator[](int u) const { return m_lists[u]; }
	ListType &operator[](int u){ return m_lists[u]; }
};
}
namespace lc {
template <class EdgeType>
struct ResidualEdge : public EdgeType {
	int rev;
	template <class... Args>
	ResidualEdge(int rev, Args&&... args)
		: EdgeType(args...)
		, rev(rev)
	{ }
};
template <class EdgeType>
class ResidualAdjacencyList
	: public AdjacencyList<ResidualEdge<EdgeType>>
{
public:
	explicit ResidualAdjacencyList(int n = 0)
		: AdjacencyList<ResidualEdge<EdgeType>>(n)
	{ }
};
template <class EdgeType>
ResidualAdjacencyList<EdgeType> make_residual(const AdjacencyList<EdgeType> &graph){
	typedef decltype(EdgeType().capacity) capacity_type;
	const int n = graph.size();
	ResidualAdjacencyList<EdgeType> result(n);
	for(int u = 0; u < n; ++u){
		for(const auto &e : graph[u]){
			const int v = e.to;
			const int rev_u = result[v].size();
			const int rev_v = result[u].size();
			result[u].emplace_back(rev_u, e);
			result[v].emplace_back(rev_v, e);
			result[v].back().to = u;
			result[v].back().capacity = capacity_type();
			result[v].back().weight = -e.weight;
		}
	}
	return result;
}
}
namespace lc {
template <class EdgeType>
auto mincostflow_primal_dual(
	int source, int sink, decltype(EdgeType().capacity) flow,
	ResidualAdjacencyList<EdgeType> &graph)
	-> decltype(EdgeType().weight)
{
	typedef decltype(EdgeType().weight) weight_type;
	typedef decltype(EdgeType().capacity) capacity_type;
	typedef std::pair<weight_type, int> weighted_pair;
	const weight_type inf = std::numeric_limits<weight_type>::max();
	const int n = graph.size();
	weight_type result = 0;
	std::vector<weight_type> h(n);
	std::vector<int> prev_vertex(n), prev_edge(n);
	while(flow > 0){
		std::priority_queue<
			weighted_pair, std::vector<weighted_pair>,
			std::greater<weighted_pair>> pq;
		std::vector<weight_type> dist(n, inf);
		dist[source] = weight_type();
		pq.push(std::make_pair(dist[source], source));
		while(!pq.empty()){
			weighted_pair p = pq.top();
			pq.pop();
			const int u = p.second;
			if(dist[u] < p.first){ continue; }
			for(size_t i = 0; i < graph[u].size(); ++i){
				const auto &e = graph[u][i];
				if(e.capacity <= 0){ continue; }
				const int v = e.to;
				const auto new_dist = dist[u] + e.weight + h[u] - h[v];
				if(dist[v] <= new_dist){ continue; }
				dist[v] = new_dist;
				prev_vertex[v] = u;
				prev_edge[v] = i;
				pq.push(std::make_pair(new_dist, v));
			}
		}
		if(dist[sink] >= inf){ return -1; }
		for(int i = 0; i < n; ++i){ h[i] += dist[i]; }
		weight_type diff = flow;
		for(int v = sink; v != source; v = prev_vertex[v]){
			diff = std::min(
				diff, graph[prev_vertex[v]][prev_edge[v]].capacity);
		}
		flow -= diff;
		result += diff * h[sink];
		for(int v = sink; v != source; v = prev_vertex[v]){
			auto &e = graph[prev_vertex[v]][prev_edge[v]];
			e.capacity -= diff;
			graph[v][e.rev].capacity += diff;
		}
	}
	return result;
}
}
using namespace std;
typedef lc::EdgeWithWeightAndCapacity<int, int> Edge;
int main(){
	ios_base::sync_with_stdio(false);
	int n;
	string s, t;
	cin >> n >> s >> t;
	vector<int> s_hist(26), t_hist(26);
	for(int i = 0; i < n; ++i){ ++s_hist[s[i] - 'a']; }
	for(int i = 0; i < n; ++i){ ++t_hist[t[i] - 'a']; }
	lc::AdjacencyList<Edge> graph(26 + 26 + 2);
	const int source = 26 + 26, sink = source + 1;
	for(int i = 0; i < 26; ++i){
		graph.add_edge(source, i, 0, 1);
		graph.add_edge(26 + i, sink, 0, 1);
		for(int j = 0; j < 26; ++j){
			const int cost = abs(s_hist[i] - t_hist[j]);
			graph.add_edge(i, 26 + j, cost, 1);
		}
	}
	auto residual = lc::make_residual(graph);
	const int f = lc::mincostflow_primal_dual(source, sink, 26, residual);
	cout << f / 2 << endl;
	return 0;
}
### Prompt

Develop a solution in Cpp to the problem described below:

Problem

Jennifer and Marian presented Carla with the string S.
However, Carla is not happy to receive the string S.
I wanted the string T.
The three decided to work together to change the string S to the string T.


Jennifer first sorts the letters in any order.

Marian then exchanges the lowercase letters of the two alphabets any number of times.
This operation exchanges all the same characters in the string, for example:


* aab-> Swap a and b-> bba
* aab-> Swap a and c-> ccb



Finally, Carla replaces one character with another and repeats until T.
Jennifer and Marian decided to try to reduce the number of Carla replacements.
Find the minimum number of replacements that Carla makes.

Constraints

* 1 ≤ n ≤ 105
* S and T contain only'a'~'z'
* | S | = | T | = n

Input


n
S
T


The length n of the string is given on the first line.
The character string S is given on the second line, and the character string T is given on the third line.

Output

Print the minimum number of Carla replacements on one line.

Examples

Input

3
abc
xyz


Output

0


Input

5
aaabb
xyxyz


Output

1

### Response

```cpp
#include <utility>
#include <queue>
#include <type_traits>
#include <cstdlib>
#include <algorithm>
#include <functional>
#include <vector>
#include <string>
#include <limits>
#include <iostream>
namespace lc {
template <class WeightType, class CapacityType>
struct EdgeWithWeightAndCapacity {
	int to;
	WeightType weight;
	CapacityType capacity;
	EdgeWithWeightAndCapacity() : to(0), weight(), capacity() { }
	EdgeWithWeightAndCapacity(
		int to, const WeightType &weight, const CapacityType &capacity)
		: to(to), weight(weight), capacity(capacity)
	{ }
};
}
namespace lc {
template <typename EdgeType>
class AdjacencyList {
public:
	typedef std::vector<EdgeType> ListType;
private:
	std::vector<ListType> m_lists;
public:
	explicit AdjacencyList(int n = 0)
		: m_lists(n)
	{ }
	int size() const { return m_lists.size(); }
	template <typename... Args>
	void add_edge(int u, Args&&... args){
		m_lists[u].emplace_back(args...);
	}
	const ListType &operator[](int u) const { return m_lists[u]; }
	ListType &operator[](int u){ return m_lists[u]; }
};
}
namespace lc {
template <class EdgeType>
struct ResidualEdge : public EdgeType {
	int rev;
	template <class... Args>
	ResidualEdge(int rev, Args&&... args)
		: EdgeType(args...)
		, rev(rev)
	{ }
};
template <class EdgeType>
class ResidualAdjacencyList
	: public AdjacencyList<ResidualEdge<EdgeType>>
{
public:
	explicit ResidualAdjacencyList(int n = 0)
		: AdjacencyList<ResidualEdge<EdgeType>>(n)
	{ }
};
template <class EdgeType>
ResidualAdjacencyList<EdgeType> make_residual(const AdjacencyList<EdgeType> &graph){
	typedef decltype(EdgeType().capacity) capacity_type;
	const int n = graph.size();
	ResidualAdjacencyList<EdgeType> result(n);
	for(int u = 0; u < n; ++u){
		for(const auto &e : graph[u]){
			const int v = e.to;
			const int rev_u = result[v].size();
			const int rev_v = result[u].size();
			result[u].emplace_back(rev_u, e);
			result[v].emplace_back(rev_v, e);
			result[v].back().to = u;
			result[v].back().capacity = capacity_type();
			result[v].back().weight = -e.weight;
		}
	}
	return result;
}
}
namespace lc {
template <class EdgeType>
auto mincostflow_primal_dual(
	int source, int sink, decltype(EdgeType().capacity) flow,
	ResidualAdjacencyList<EdgeType> &graph)
	-> decltype(EdgeType().weight)
{
	typedef decltype(EdgeType().weight) weight_type;
	typedef decltype(EdgeType().capacity) capacity_type;
	typedef std::pair<weight_type, int> weighted_pair;
	const weight_type inf = std::numeric_limits<weight_type>::max();
	const int n = graph.size();
	weight_type result = 0;
	std::vector<weight_type> h(n);
	std::vector<int> prev_vertex(n), prev_edge(n);
	while(flow > 0){
		std::priority_queue<
			weighted_pair, std::vector<weighted_pair>,
			std::greater<weighted_pair>> pq;
		std::vector<weight_type> dist(n, inf);
		dist[source] = weight_type();
		pq.push(std::make_pair(dist[source], source));
		while(!pq.empty()){
			weighted_pair p = pq.top();
			pq.pop();
			const int u = p.second;
			if(dist[u] < p.first){ continue; }
			for(size_t i = 0; i < graph[u].size(); ++i){
				const auto &e = graph[u][i];
				if(e.capacity <= 0){ continue; }
				const int v = e.to;
				const auto new_dist = dist[u] + e.weight + h[u] - h[v];
				if(dist[v] <= new_dist){ continue; }
				dist[v] = new_dist;
				prev_vertex[v] = u;
				prev_edge[v] = i;
				pq.push(std::make_pair(new_dist, v));
			}
		}
		if(dist[sink] >= inf){ return -1; }
		for(int i = 0; i < n; ++i){ h[i] += dist[i]; }
		weight_type diff = flow;
		for(int v = sink; v != source; v = prev_vertex[v]){
			diff = std::min(
				diff, graph[prev_vertex[v]][prev_edge[v]].capacity);
		}
		flow -= diff;
		result += diff * h[sink];
		for(int v = sink; v != source; v = prev_vertex[v]){
			auto &e = graph[prev_vertex[v]][prev_edge[v]];
			e.capacity -= diff;
			graph[v][e.rev].capacity += diff;
		}
	}
	return result;
}
}
using namespace std;
typedef lc::EdgeWithWeightAndCapacity<int, int> Edge;
int main(){
	ios_base::sync_with_stdio(false);
	int n;
	string s, t;
	cin >> n >> s >> t;
	vector<int> s_hist(26), t_hist(26);
	for(int i = 0; i < n; ++i){ ++s_hist[s[i] - 'a']; }
	for(int i = 0; i < n; ++i){ ++t_hist[t[i] - 'a']; }
	lc::AdjacencyList<Edge> graph(26 + 26 + 2);
	const int source = 26 + 26, sink = source + 1;
	for(int i = 0; i < 26; ++i){
		graph.add_edge(source, i, 0, 1);
		graph.add_edge(26 + i, sink, 0, 1);
		for(int j = 0; j < 26; ++j){
			const int cost = abs(s_hist[i] - t_hist[j]);
			graph.add_edge(i, 26 + j, cost, 1);
		}
	}
	auto residual = lc::make_residual(graph);
	const int f = lc::mincostflow_primal_dual(source, sink, 26, residual);
	cout << f / 2 << endl;
	return 0;
}
```