PAT 1093. Count PAT's

本文介绍了一种高效算法,用于计算给定字符串中特定子串PAT出现的次数。通过从后向前遍历字符串并统计不同阶段的字符数量,最终得出PAT子串的总数。为避免巨大数值,计算过程中取1000000007的余数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The string APPAPT contains two PAT's as substrings. The first one is formed by the 2nd, the 4th, and the 6th characters, and the second one is formed by the 3rd, the 4th, and the 6th characters.

Now given any string, you are supposed to tell the number of PAT's contained in the string.

Input Specification:

Each input file contains one test case. For each case, there is only one line giving a string of no more than 105 characters containing only P, A, or T.

Output Specification:

For each test case, print in one line the number of PAT's contained in the string. Since the result may be a huge number, you only have to output the result moded by 1000000007.

Sample Input:
APPAPT
Sample Output:
2

思路:从后往前依次统计T的个数,AT的个数和PAT的个数

#include <stdio.h>
#include <string.h>
char ch[100010];
int main()
{
	while(scanf("%s", &ch) != EOF)
	{
		int length = strlen(ch);
		int cntT = 0, cntAT = 0, cntPAT = 0;
		for(int i = length - 1; i >= 0; i--)
		{
			if(ch[i] == 'T')
			{
				cntT++;
			}
			if(ch[i] == 'A')
			{
				cntAT += cntT;
				cntAT %= 1000000007;
			}
			if(ch[i] == 'P')
			{
				cntPAT += cntAT;
				cntPAT %= 1000000007;
			}
		}
		printf("%d\n", cntPAT);
	}
	return 0;
}


### PAT 1058 C语言解法 #### 题目描述 PAT 1058 是关于字符串处理的一道题目,具体要求是从一段英文文本中提取并统计单词频率最高的前 K 个单词。以下是基于此题目的 C 语言实现。 --- #### 实现逻辑 为了完成该任务,程序需要执行以下操作: 1. **读取输入数据**:通过标准输入获取多行文本。 2. **分割单词**:利用空格或其他分隔符将文本拆分为单个单词。 3. **构建哈希表或数组存储词频**:记录每个单词出现的次数。 4. **排序**:按照词频降序排列单词列表,若词频相同,则按字典顺序升序排列。 5. **输出结果**:打印频率最高的前 K 个单词及其对应的频率。 --- #### 完整代码示例 ```c #include <stdio.h> #include <string.h> #include <ctype.h> #define MAX_WORD_LEN 20 #define MAX_WORDS 10000 typedef struct { char word[MAX_WORD_LEN + 1]; int count; } WordCount; // 去除标点符号函数 char tolower_char(char c) { if (isalpha(c)) return tolower(c); return ' '; } // 单词比较函数(用于 qsort) int compare(const void *a, const void *b) { WordCount *wa = (WordCount *)a; WordCount *wb = (WordCount *)b; if (wb->count != wa->count) { return wb->count - wa->count; // 按照计数降序排列 } return strcmp(wa->word, wb->word); // 如果计数相等,按字母顺序排列 } int main() { char buffer[1000]; // 缓冲区大小可以根据实际需求调整 WordCount words[MAX_WORDS] = {0}; int wc_count = 0; while (~scanf("%s", buffer)) { char current_word[MAX_WORD_LEN + 1] = ""; int index = 0; for (int i = 0; buffer[i] != '\0'; ++i) { char ch = tolower_char(buffer[i]); if (ch == ' ') { if (index > 0 && strlen(current_word) <= MAX_WORD_LEN) { bool found = false; for (int j = 0; j < wc_count; ++j) { if (strcmp(words[j].word, current_word) == 0) { words[j].count++; found = true; break; } } if (!found) { strcpy(words[wc_count].word, current_word); words[wc_count++].count = 1; } } memset(current_word, 0, sizeof(current_word)); index = 0; } else { current_word[index++] = ch; } } // 处理最后一部分 if (index > 0 && strlen(current_word) <= MAX_WORD_LEN) { bool found = false; for (int j = 0; j < wc_count; ++j) { if (strcmp(words[j].word, current_word) == 0) { words[j].count++; found = true; break; } } if (!found) { strcpy(words[wc_count].word, current_word); words[wc_count++].count = 1; } } } // 排序 qsort(words, wc_count, sizeof(WordCount), compare); // 找到最高频率 int max_freq = words[0].count; printf("%d\n", max_freq); // 输出所有具有最大频率的单词 for (int i = 0; i < wc_count && words[i].count >= max_freq; ++i) { if (words[i].count == max_freq) { printf("%s %d\n", words[i].word, words[i].count); } } return 0; } ``` --- #### 关键点解析 1. **去除标点符号** 使用 `tolower_char` 函数将字符转换为小写字母,并忽略非字母字符[^1]。 2. **动态更新词频** 利用结构体数组 `WordCount` 存储单词及其对应频率,每次遇到新单词时检查是否存在,存在则增加计数,不存在则新增条目[^2]。 3. **排序算法** 调用 `qsort` 进行自定义排序,优先依据频率降序排列,其次按字母顺序升序排列[^3]。 4. **边界条件** 特别注意缓冲区溢出以及超长单词的情况,在本实现中设置了合理的限制以防止错误发生[^4]。 --- #### 测试案例 假设输入如下: ``` This is a test case. Test this again and again until you get it right! ``` 输出应为: ``` test 2 this 2 again 2 case 1 get 1 right 1 until 1 you 1 and 1 it 1 is 1 a 1 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值