这是其中一个问题,在任何更高级别的语言中都是小菜一碟,但是当用纯C语言编写它时,我不知道该怎么做才能不把我的代码变成一团糟:
我有一个独特字母的字母,一个带有一些数字的字符串,例如“test01test21”。我需要生成所有字符串,这些字符串是用字母替换数字所以(因此每个数字0,1,2,...得到它的字母(不一定是唯一的),我们需要迭代所有可能的字母数字替换,以便生成所有字符串),并以某种方式返回这些字符串。
问题似乎很容易,但我想的越多,问题就越多。当返回结果时,我已经编码了动态字符串列表结构,因此它不是主要问题。我想知道的是如何遍历所有字母数字替换(请记住,数字集不是常数,要在一个字符串中替换的数字可能是{0,1,2}而在另一个字符串中{例如,3,7,9},但它总是一些数字集合,这里有几个我想过的方法:
我真的想不出别的什么。我认为这两种方式都存在缺陷,导致代码非常复杂。问题是 - 当你必须在C中解决这类问题时该怎么办?我会感谢任何有助于我编写代码并以某种方式组织代码的提示......
示例输出:
字母“ab”
字符串“ab01”
输出{“abaa”,“abab”,“abba”,“abbb”}
答案 0 :(得分:6)
您必须使用tries
数据结构。只需开始阅读您的字符串并构建tries
即可。
让我们举个例子,它应该是这样的。
a a
| |
b b
| / \
0 --> a b
| / \ / \
1 a b a
| | |
\0 \0 \0
上面例子中按字符构建的字符:
a ------ b ------- 0 ------- 1 ------- \0
a ----> a ------> a ------> a ------> a
| | | | |
\0 >b b b b
| / \ / \ / \
\0 >a b a >b a b
| | / \ | / \ / \
\0 \0 a b \0 a b a
| | | | |
\0 \0 \0 \0 \0
|
|
v
a
|
b
/ \
a b
/ \ / \
a b a
| | |
\0 \0 \0
答案 1 :(得分:2)
扩展我上面的评论:你甚至不需要任何奇特的数据结构。
这是一段非常简单的代码(错误处理和其他铃声以及为了清晰起见而省略的哨声),它们会产生重复的变化:
char the_string[] = "abc12def34";
char *digit_pos[strlen(the_string)];
char replacements[] = "XYZ";
int n = strlen(replacements);
// memoize all digit positions
int k = 0;
for (char *p = the_string; *p; p++)
if (isdigit(*p))
digit_pos[k++] = p;
// generate all variations
int bound = pow(n, k);
for (int i = 0; i < bound; i++) {
// convert 'i' to its digits;
// use them to index into replacements array
int tmp = i;
for (int j = 0; j < k; j++) {
*digit_pos[j] = replacements[tmp % n];
tmp /= n;
}
printf("%s\n", the_string);
}
答案 2 :(得分:1)
这是一个递归算法,我认为它更接近您的用例:
#include <stdio.h>
#include <string.h>
void printone(const char *alphabet, int rep[], const char *str) {
char buf[strlen(str) + 1];
int i, c;
for (i = 0; (c = str[i]) != '\0'; i++) {
if (c >= '0' && c <= '9')
c = alphabet[rep[c - '0']];
buf[i] = (char)c;
}
buf[i] = '\0';
puts(buf);
}
int printrec(const char *alphabet, int alen, int rep[], int digit, int maxd, const char *str) {
int count = 0;
for (;; digit++) {
if (digit >= maxd) {
printone(alphabet, rep, str);
return 1;
}
if (!strchr(str, '0' + digit))
continue;
for (rep[digit] = 0; rep[digit] < alen; rep[digit]++) {
count += printrec(alphabet, alen, rep, digit + 1, maxd, str);
}
return count;
}
}
int main(int argc, char **argv) {
if (argc < 3) {
fprintf(stderr, "usage: %s alphabet string\n", argv[0]);
return 1;
} else {
int rep[10];
int count = printrec(argv[1], strlen(argv[1]), rep, 0, 10, argv[2]);
fprintf(stderr, "%d combinations\n", count);
return 0;
}
}