我正在检查2个字符串是否是排列。我对字符串进行排序,然后将每个字符相互比较。但是,我认为我的排序过程也改变了原始字符串(我用指针和通过引用传递非常糟糕)。
有没有办法在不修改原始字符串的情况下进行检查?
我也试过使用strcpy,但我真的不知道如何使用它。 我在check()函数中试过这个:
void check(char *word, struct Entry *en) {
if (areAnagram(en->word, word) == 1) {
//printf("EW:%s W:%s\n", en->word, word);
//For example, this should return something like
// EW:silent W:listen
//But I got
// EW:eilnst W:eilnst
}
}
以下是我的代码。我从另一个函数调用areAnagram函数:
typedef struct Entry {
char *word;
int len;
struct Entry *next;
} Entry;
参赛作品结构:
void quickSort(char *arr, int si, int ei);
int areAnagram(char *str1, char *str2)
{
// Get lenghts of both strings
int n1 = strlen(str1);
int n2 = strlen(str2);
// If lenght of both strings is not same, then they cannot be anagram
if (n1 != n2) {
return 0;
}
// Sort both strings
quickSort (str1, 0, n1 - 1);
quickSort (str2, 0, n2 - 1);
int i;
// Compare sorted strings
for (i = 0; i < n1; i++) {
if (str1[i] != str2[i]) {
return 0;
}
}
return 1;
}
void exchange(char *a, char *b)
{
char temp;
temp = *a;
*a = *b;
*b = temp;
}
int partition(char A[], int si, int ei)
{
char x = A[ei];
int i = (si - 1);
int j;
for (j = si; j <= ei - 1; j++) {
if(A[j] <= x) {
i++;
exchange(&A[i], &A[j]);
}
}
exchange (&A[i + 1], &A[ei]);
return (i + 1);
}
void quickSort(char A[], int si, int ei)
{
int pi; /* Partitioning index */
if(si < ei) {
pi = partition(A, si, ei);
quickSort(A, si, pi - 1);
quickSort(A, pi + 1, ei);
}
}
这是anagram检查过程:
{{1}}
答案 0 :(得分:3)
有一种更好的方法可以检查两个字符串是否为字谜。您可以创建一个数组来存储第一个字符串中每个字符的计数(增加数组中的ASCII值索引)。然后遍历第二个字符串并减少每个字符的计数(数组中的ASCII值索引)。现在检查数组的所有元素是否为零,如果是,则这些是anagrams,否则不是。
int arr [123]; 假设两个字符串是s1 =&#34; abba&#34;和s2 =&#34; baba&#34;
在遍历第一个字符串arr [97] = 2时,arr [98] = 2;
遍历第二个数组arr [97] = 0,arr [98] = 0;
现在,如果遍历整个数组,那么所有元素都将为零。
但如果两个字符串s1 =&#34; abba&#34;和s2 =&#34; abac&#34;
在遍历第一个字符串arr [97] = 2时,arr [98] = 2;
遍历第二个字符串arr [97] = 0时,,arr [98] = 1,arr [99] = - 1;
由于数组的所有元素都不为零,因此这些不是字谜。
上述算法的复杂性为O(n)。
希望它有所帮助。
答案 1 :(得分:0)
使用strcpy制作副本:
char *copy = malloc(strlen(word) + 1); // can use a temporary buffer, but this allows variable length inputs
strcpy(copy, word);
// use copy as your temporary string
free(copy);
答案 2 :(得分:0)
您的标题声明您不想修改原始字符串,但是您的解决方案使用Quicksort修改字符串。此外,排序 - 即使是快速优化的排序 - 也是一项昂贵的操作,并且不是您要解决的问题所必需的。您可以使用查找表来获得速度,但不会修改原始字符串。您只需为每个字母创建一个唯一编号,然后对这些值求和。等额将构成一个字谜。
/* OPTION 1: let the compiler build your table */
static const int A=0x0000001;
static const int B=0x0000002;
static const int C=0x0000004;
/* continue to double for other letters until ... */
static const int Z=0x4000000;
/* OPTION 2: calculate a cheap hash for each letter */
/* Returns 0 for anagram similar to strcmp */
int anagram (const char* word1, const char* word2)
{
/* strings must be equal length */
if (strlen(word1) != strlen(word2))
return -1;
unsigned long sum1 = 0;
unsigned long sum2 = 0;
char c;
for (int i = 0 ; word1[i] != '\0' ; i++)
{
/* use toupper() function here if case insensitive */
c = toupper(word1[i]);
sum1 += 1 << (c - 'A');
}
for (int i = 0 ; word2[i] != '\0' ; i++)
{
/* use toupper() function here if case insensitive */
c = toupper(word2[i]);
sum2 += 1 << (c - 'A');
}
return (int)(sum1 - sum2); /* ignore overflow */
}
上面的anagram函数未经测试,为清楚起见而编写。您需要包含ctype.h
才能使用toupper()
转换案例。
最后,您可以复制其中一个字符串,遍历每个字符上调用strchr()
的另一个字符串,以查找副本中的匹配字符。如果strchr()
返回NULL,则没有anagram,否则如果strchr()
返回有效指针,则使用它来修改副本,例如设置为char值为0x01,以便您可以对修改后的副本中的字符求和。在这种情况下,如果修改后的副本中所有字符的总和等于比较字符串的整数长度,则字符串将是字谜。