Ответ 1
Самый простой способ - это, вероятно, одновременное перемещение обеих строк вручную и создание словаря (который сопоставляет соответствующие символы), когда вы это делаете:
if(input1.Length != input2.Length)
return false;
var characterMap = new Dictionary<char, char>();
for(int i = 0; i < input1.Length; i++)
{
char char1 = input1[i];
char char2 = input2[i];
if(!characterMap.ContainsKey(char1))
{
if (characterMap.ContainsValue(char2))
return false;
characterMap[char1] = char2;
}
else
{
if(char2 != characterMap[char1])
return false;
}
}
return true;
Таким же образом вы можете создать регулярное выражение. Это, конечно, не более эффективно для одного сравнения, но может быть полезно, если вы хотите в один момент проверить один шаблон повторения на несколько строк. На этот раз мы связываем символы с их обратными ссылками.
var characterMap = new Dictionary<char, int>();
string regex = "^";
int nextBackreference = 1;
for(int i = 0; i < input.Length; i++)
{
char character = input[i];
if(!characterMap.ContainsKey(character))
{
regex += "(.)";
characterMap[character] = nextBackreference;
nextBackreference++;
}
else
{
regex += (@"\" + characterMap[character]);
}
}
regex += "$";
Для matter
он сгенерирует это регулярное выражение: ^(.)(.)(.)\3(.)(.)$
. Для acquaintance
это: ^(.)(.)(.)(.)\1(.)(.)(.)\1\6\2(.)$
. Если бы, конечно, впоследствии можно было бы оптимизировать это регулярное выражение (например, для второго ^(.)(.)..\1.(.).\1\3\2$
), но в любом случае это даст вам многоразовое регулярное выражение, которое проверяет этот единственный шаблон повторения.
EDIT: Обратите внимание, что данное задание регулярного выражения имеет оговорку. Он позволяет отображать несколько символов во входной строке на один символ в тестовых строках (что противоречило бы вашему последнему примеру). Чтобы получить правильное решение регулярных выражений, вам нужно сделать еще один шаг, чтобы запретить сопоставляемые символы. Поэтому acquaintance
должен был бы генерировать это ужасное регулярное выражение:
^(.)(?!\1)(.)(?!\1|\2)(.)(?!\1|\2|\3)(.)\1(?!\1|\2|\3|\4)(.)(?!\1|\2|\3|\4|\5)(.)(?!\1|\2|\3|\4|\5|\6)(.)\1\6\2(?!\1|\2|\3|\4|\5|\6|\7)(.)$
И я не могу придумать более простой способ, так как вы не можете использовать обратные ссылки в (отрицательных) классах символов. Так что, возможно, если вы do хотите утверждать это, регулярные выражения не являются лучшим вариантом в конце.
Отказ от ответственности: я на самом деле не .NET-гуру, поэтому это может быть не самая лучшая практика при прохождении через массивы при создании словаря или строки. Но я надеюсь, что вы можете использовать его в качестве отправной точки.