问题来自 TopCoder SRM 591 DIV 2 的第二题:
Problem Statement
Let X and Y be two strings of equal length, consisting of uppercase English letters only. The two strings are called convertible if there is a permutation P of the English alphabet with the following property: if each character c in the string X is replaced by the character P(c), we obtain the string Y. (In other words, X and Y are convertible iff the following holds: whenever two letters of X are equal, the corresponding two letters of Y must be equal, and vice versa.) For example, consider the string "ABCA". We can choose to replace each 'A' by a 'F', each 'B' by a 'B', and each 'C' by a 'G', obtaining the string "FBGF". Thus the strings "ABCA" and "FBGF" are convertible. The strings "ABCA" and "EFGH" are not convertible, because the two 'A's in the first string must correspond to the same letter in the second string. The strings "ABCA" and "EEEE" are not convertible, because different letters in the first string must correspond to different letters in the second string. You are given two strings A and B of the same length. These strings only contain English letters from 'A' to 'I', inclusive. (That is, only the first 9 letters of the alphabet are used.) You want to change A and B into two strings that are convertible. The only allowed change is to choose some indices (possibly none) and to remove the characters at those indices from each of the strings. (I.e., the removed characters must be at the same positions in both strings. For example, it is not allowed to only remove character 0 of A and character 3 of B.) For example, if A="ABAC", B="AHHA" and the chosen indices are 0 and 2, then the resulting strings will be "BC" and "HA". Our goal is to choose as few indices as possible, given that after the erasing we want to obtain two convertible strings. Compute and return the smallest possible number of chosen indices.
Definition
Class:
ConvertibleStrings
Method:
leastRemovals
Parameters:
string, string
Returns:
int
Method signature:
int leastRemovals(string A, string B)
(be sure your method is public)
Constraints
-
A will contain between 1 and 50 characters, inclusive.
-
A and B will be of the same length.
-
A will contain characters from 'A' to 'I' only.
-
B will contain characters from 'A' to 'I' only.
我的思路是穷举A中字母与B中字母的对应关系,看哪种对应需要删除的字母最少,这一最少值即是答案。
穷举对应关系,就是生成全排列。
我生成全排列的方式是回溯。
之后看其他人的代码,发现一个由给定排列求出其下一个排列的函数,于是学习一下,自己实现如下:
// 生成下一字典序排列
// 假设a中元素互不相同
// 若已经是最后一个字典序排列,则返回0,否则返回1
int next_permutation( int a[], int n ) {
int i, j;
for ( i = n-1; (0 < i) && (a[i-1] > a[i]); --i ) {
}
if ( 0 >= i ) {
return 0;
}
for ( j = n-1; j >= i; --j ) {
if ( a[ j ] > a[ i-1 ] ) {
int tmp = a[ i-1 ];
a[ i-1 ] = a[ j ];
a[ j ] = tmp;
j = n - 1;
while ( i < j ) {
tmp = a[ i ];
a[ i ] = a[ j ];
a[ j ] = tmp;
++i; --j;
}
break;
}
}
return 1;
}
还有人使用的是C++的 <algorithm> 中 next_permutation 函数,功能一样。