使用scanf读取特定单词时循环无法退出导致TLE问题排查
解决你的单词统计程序TLE问题
看起来你的程序超时(TLE)主要有两个核心原因:scanf的EOF处理不严谨,以及单词匹配的效率太低。咱们一步步来修复:
1. 修复inputTextTxt的循环退出逻辑
你当前的inputTextTxt函数里,第一个scanf("%*[^a-zA-Z0-9_]")没有检查返回值。当输入到达EOF时,这个scanf会返回EOF,但代码会继续执行后面的读取操作。虽然理论上后续的scanf会返回EOF触发break,但在某些评测环境下,这种未处理的EOF可能导致循环重复执行无效的读取操作,浪费时间。
修改后的inputTextTxt应该在跳过非目标字符后立即检查EOF:
void inputTextTxt(void) { for (;;) { // 跳过非字母数字下划线,同时检查是否到达EOF int skip_status = scanf("%*[^a-zA-Z0-9_]"); if (skip_status == EOF) { break; } int cnt = scanf("%2047[a-zA-Z0-9_]", tmp); if (cnt != 1) { break; } for (size_t i = 0; i < dic_actual_num; ++i) { if (strcmp(dicWord[i], tmp) == 0) { dicWcount[i]++; } } } }
2. 优化单词匹配效率(关键解决TLE)
你现在的统计逻辑是每个文本单词遍历整个字典,时间复杂度是O(M*N)(M是文本单词数,N是字典大小)。当字典和文本规模较大时,这种线性遍历会非常慢,直接导致超时。
解决方法是把字典排序后用二分查找,不需要额外的库依赖:
步骤1:准备排序的字典条目
在main函数中,inputDicTxt执行完毕后,创建一个结构体数组保存字典单词和对应的计数指针,然后排序:
// 定义结构体保存字典条目 typedef struct { char* word; int* count_ptr; } DictEntry; int main() { inputDicTxt(); // 为二分查找准备排序的字典条目 DictEntry* sorted_entries = malloc(dic_actual_num * sizeof(DictEntry)); for (int i = 0; i < dic_actual_num; ++i) { sorted_entries[i].word = dicWord[i]; sorted_entries[i].count_ptr = &dicWcount[i]; } // 排序字典条目(按单词字典序) int compare_entries(const void* a, const void* b) { const DictEntry* entry_a = (const DictEntry*)a; const DictEntry* entry_b = (const DictEntry*)b; return strcmp(entry_a.word, entry_b.word); } qsort(sorted_entries, dic_actual_num, sizeof(DictEntry), compare_entries); // 修改inputTextTxt的调用,传入排序后的条目和字典大小 inputTextTxt(sorted_entries, dic_actual_num); // ... 后续的找最大值、输出、释放内存逻辑 free(sorted_entries); // 别忘了释放这个数组 return 0; }
步骤2:修改inputTextTxt用二分查找
void inputTextTxt(DictEntry* sorted_entries, int dic_size) { for (;;) { int skip_status = scanf("%*[^a-zA-Z0-9_]"); if (skip_status == EOF) { break; } int cnt = scanf("%2047[a-zA-Z0-9_]", tmp); if (cnt != 1) { break; } // 构造查找键 DictEntry search_key = {.word = tmp}; // 二分查找单词 DictEntry* found = bsearch(&search_key, sorted_entries, dic_size, sizeof(DictEntry), compare_entries); if (found != NULL) { // 找到则计数+1 (*(found->count_ptr))++; } } }
这样每个单词的查找时间复杂度降到O(logN),整体统计效率会大幅提升,彻底解决超时问题。
3. 修复字典输入的分隔符判断逻辑
你的inputDicTxt里用strcmp(tmp, divider) >= 0来判断分隔符,这会把任何比-----长的-序列(比如------)误判为分隔符,导致字典输入提前结束,后续出现错误答案(WA)。应该改成精确匹配:
if (cnt_divider) { if (strcmp(tmp, divider) == 0) { // 这里改成==0,精确匹配5个'-' dicWcount = calloc(dic_actual_num, sizeof(*dicWcount)); break; } }
这些修改应该能同时解决你的TLE和潜在的WA问题。
内容的提问来源于stack exchange,提问作者LINPOHSIEN
相关产品推荐
相关产品推荐

