You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何程序无法识别字符串重复单词?重排数计算出错求助

单词重排计数程序的错误分析与修正

问题场景

需要编写程序:输入整数T后读取T行字符串,输出字符串的单词重排方式数(公式为:总单词数的阶乘 ÷ 每个重复单词出现次数的阶乘的乘积)。现有代码测试时:

  • 输入T=2,第一行字符串"no way no good",输出正确结果12(对应4!/2!);
  • 第二行字符串"yes no yes yes no",正确结果应为5!/(3!2!)=10,但程序输出120,明显错误。

错误原因分析

现有代码的核心问题在于重复单词的识别与统计逻辑完全错误,具体如下:

1. 重复单词的匹配逻辑漏洞

代码通过遍历字符,仅当line[k]是空格且line[k+1]等于line[j]时才开始比较后续字符,直到两者同时遇到空格才判定为重复单词。这种方式:

  • 会漏掉非相邻的重复单词匹配(比如第一个yes和第三个yes的匹配可能因为遍历顺序问题被忽略);
  • 错误地从单词中间字符开始匹配,导致无效比较或漏判。

2. 重复次数的统计逻辑混乱

代码中count变量的处理逻辑完全不符合需求:

  • 初始count=1,每找到一对重复单词就count++,然后用ans / fact(count),接着重置count=0;
  • 对于出现3次的单词(如测试用例中的yes),代码会两次触发重复判定,每次除以2!,最终相当于除以2!*2!,而非正确的3!,导致结果错误。

3. 未正确分割单词

代码仅通过统计空格数得到总单词数,但没有将字符串分割为独立单词,无法准确统计每个单词的出现次数,这是所有错误的根源。

修正方案

正确的思路是先分割字符串为单词数组,统计每个单词的出现次数,再按公式计算结果:

修正后的代码示例

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

// 计算阶乘,处理n=0的情况(0! = 1)
long long fact(int n) {
    long long result = 1;
    for (int i = 2; i <= n; i++) {
        result *= i;
    }
    return result;
}

int main() {
    int T;
    scanf("%d", &T);
    // 清除换行符
    getchar();

    for (int i = 0; i < T; i++) {
        char line[200];
        fgets(line, sizeof(line), stdin);
        // 去掉末尾的换行符
        line[strcspn(line, "\n")] = '\0';

        int word_count = 0;
        char* words[50]; // 假设最多50个单词
        char* ptr = line;

        // 分割字符串为单词数组
        while (*ptr != '\0') {
            // 跳过开头的空格
            while (*ptr == ' ') ptr++;
            if (*ptr == '\0') break;
            words[word_count++] = ptr;
            // 找到单词的结尾(空格或字符串末尾)
            while (*ptr != ' ' && *ptr != '\0') ptr++;
            if (*ptr != '\0') {
                *ptr = '\0'; // 将空格替换为结束符,分割单词
                ptr++;
            }
        }

        // 计算总单词数的阶乘
        long long ans = fact(word_count);

        // 统计每个单词的出现次数,并计算除法
        int visited[50] = {0}; // 标记已统计的单词
        for (int j = 0; j < word_count; j++) {
            if (visited[j]) continue;
            int cnt = 1;
            for (int k = j + 1; k < word_count; k++) {
                if (strcmp(words[j], words[k]) == 0) {
                    cnt++;
                    visited[k] = 1;
                }
            }
            if (cnt > 1) {
                ans /= fact(cnt);
            }
        }

        printf("%lld\n", ans);
    }

    return 0;
}

修正要点

  1. 分割单词:将字符串分割为独立的单词数组,方便后续统计;
  2. 正确统计重复次数:遍历单词数组,统计每个单词的出现次数,对次数>1的单词,用总阶乘除以该次数的阶乘;
  3. 阶乘函数优化:改用循环实现阶乘,同时处理n=0的情况(0! = 1),避免递归的栈溢出问题;
  4. 输入处理优化:用fgets读取整行,避免scanf处理换行符的问题。

内容的提问来源于stack exchange,提问作者N Tahseen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 06:45:37