如何更正此代码以检查字谜?

时间:2017-05-27 01:36:30

标签: c string pointers c-strings anagram

if (notAuthenticated()) {
    requestContext.abortWith(Response.status(401).build()));
    return;
}

我写了代码来检查两个字符串a和b是否是字谜。

误报,当 b更短的长度超过a并且是a的子字符串时。

例如。 b是“cats”,反过来是“stac”,a是“stack”代码显示a和b为anagrams

3 个答案:

答案 0 :(得分:1)

一些伪代码,用于检查两个字符串是否是彼此的字谜(使用您的变量名称):

if (strlen(a) != strlen(b))
    // Not an anagram
    return

char *a_sorted = sort_chars(a)
char *b_sorted = sort_chars(b)

// Once the characters in each word are re-arranged in alphabetical
// order, we can just test for equality. Anagrams will be equal
// (Note that this will not work on multi-word strings with differing
// numbers of whitespace characters)
if (strcmp(a_sorted, b_sorted) == 0)
    // Anagram!
else
    // Not an anagram

这里的实际工作是sort_chars(in)函数,它按字母顺序对in字符串中的字符进行排序,并返回指向包含已排序字符的新字符串的指针。使用字符的数字ASCII值(它们已经按字母顺序排列,但是有人在那里做某事!),像bubble sort(或任何其他你想要使用的排序算法) )应该工作得很好。

答案 1 :(得分:1)

首先,您正在编写的代码看起来更像是在尝试检查两个单词是回文。如果这是你的意图,那么你将获取较小字符串的长度,使la的最后一个字符出现之前命中0。

如果你不想检查回文,我会想你正在寻找代码来检查ab的排列,因为该代码与如果你只有一个单词,检查一个字谜。

不要做别人的建议并对字符串进行排序和比较。这个范围可以比三个简单的线性遍历更差,尽管有一个小的空间权衡和一个字符串中可能出现的字符串数量的界限。

逻辑是这样的:从字符到映射值的映射,指示a中存在哪些字符以及它们出现的次数。然后,一旦确定每个字符都存在,请通过b,减少出现次数。然后,再次检查b,确保所有出现次数为零。

下面:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

// Only works for single words, but you get the idea.
int palindrome(const char* a, const char* b) {
    ssize_t len_a = (ssize_t)strlen(a);
    ssize_t len_b = (ssize_t)strlen(b);
    if (len_a != len_b) return 0;

    b += (len_b - 1);
    while (len_a--) if (*a++ != *b--) return 0;
    return 1;
}

 // Really checks for a case-sensitive permutations.
int anagram(const char* a, const char* b) {
    size_t len_a = strlen(a);
    size_t len_b = strlen(b);
    if (len_a != len_b) return 0;

    uint16_t occurrences[256] = {0};

    for (; *a; occurrences[(int)*a]++, a++);
    for (; *b; occurrences[(int)*b]--, b++) 
        if (!occurrences[(int)*b]) return 0;

    b -= len_b;
    for (; *b; b++) if (occurrences[(int)*b]) return 0;

    return 1;
}

 int main(void) {
    const char *a = "stack";
    const char *b = "kcats";
    printf("anagram: %d\n", anagram(a, b));

    b = "cats";
    printf("anagram: %d\n", anagram(a, b));

    b = "kcbts";
    printf("anagram: %d\n", anagram(a, b));

    a = "aabbcdddd";
    b = "aaddddbbc";
    printf("anagram: %d\n", anagram(a, b));

    a = "aabbcddcd";
    b = "aadddddbc";
    printf("anagram: %d\n", anagram(a, b));

    return EXIT_SUCCESS;
}

请注意,当您执行这些算法中的任何一种时,如果字符串的长度不同,则会出现早期的小错误条件。

此外,为简单起见,代码区分大小写,但这很容易更改。

输出:

anagram: 1
anagram: 0
anagram: 0
anagram: 1
anagram: 0

答案 2 :(得分:0)

继续我的评论,你可以使用一个简单的频率数组(记录主题的每个字符出现的次数),并对建议的<做同样的事情em> anagram ,然后简单地比较两个频率数组,以确定提出的anagram 是否实际上是主题的字谜。

例如,您可以执行类似以下操作:

#include <stdio.h>
#include <string.h>

#define MAXF 62

int main (int argc, char **argv) {

    char *sub = argc > 1 ? argv[1] : "anagram",
         *ana = argc > 2 ? argv[2] : "nag a ram",
         *sp = sub, *ap = ana;

    int subf[MAXF] = {0},   /* subject frequency array */
        anaf[MAXF] = {0};   /* anagram frequency array */

    while (*sp) {   /* fill subject frequency array */
        if ('a' <= *sp && *sp <= 'z')
            subf[*sp - 'a']++;
        else if ('A' <= *sp && *sp <= 'Z')
            subf[*sp - 'A' + 26]++;
        else if ('0' <= *sp && *sp <= '9')
            subf[*sp - '0' + 52]++;
        sp++;
    }

    while (*ap) {   /* fill anagram frequency array */
        if ('a' <= *ap && *ap <= 'z')
            anaf[*ap - 'a']++;
        else if ('A' <= *ap && *ap <= 'Z')
            anaf[*ap - 'A' + 26]++;
        else if ('0' <= *ap && *ap <= '9')
            anaf[*ap - '0' + 52]++;
        ap++;
    }

    /* if character frequency arrays are equal - it's an anagram */
    if (memcmp (subf, anaf, MAXF * sizeof *subf) == 0)
        printf ("'%s' is an anagram of '%s'\n", ana, sub);
    else
        printf ("'%s' is NOT an anagram of '%s'\n", ana, sub);

    return 0;
}

示例使用/输出

检查anagramnag a ram

的默认值
$ ./bin/anagram
'nag a ram' is an anagram of 'anagram'

检查nag a rim是否是主题词anagram

的字谜
$ ./bin/anagram anagram "nag a rim"
'nag a rim' is NOT an anagram of 'anagram'