0
点赞
收藏
分享

微信扫一扫

P1308 [NOIP2011 普及组] 统计单词数 题解

迎月兮 2022-02-08 阅读 66
  • C 实现
// -*- coding: utf-8 -*-
//  @ Date   : 2022/5/20 13:14
//  @ Author : RichardLau_Cx
//  @ file   : Richard.c
//  @ IDE    : Dev-C++
//  @ Source : luogu

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


int main() {
	char string1[10];
	char string2[1000000];
	
	char c;
	int i, j;
	int flag;
	int p = 0;  // 子串第一次全匹配时出现的首字母位置 
	int num = 0;  // 累计相同子单词个数 
	int count = 0;  // 字符串2总长度 
	int len1, len2;
	
	scanf("%s", string1);  // 读取字符串1 
	
	// 读取字符串2(包括了空格、回车、换行、文件末等的判断) 
	while ((c = getchar()) != EOF)  {
//		printf("  -- %c --  ", c);		
		if (c != '\r' && c != '\n')
			string2[count++] = c; 
	}	
	
	while (!isalpha(string2[count-1]))  // C 库函数 void isalpha(int c) 检查所传的字符是否是字母。
		count--;
	
	string2[count] = '\0';  // 补字符串尾部结束特征
	len1 = strlen(string1);
	len2 = strlen(string2);
	
	
	// 将两个字符串中字母分别转化为大写
	for(i=0; i < len1; i++) {
		if (isalpha(string1[i]) && string1[i] >= 'a' && string1[i] <= 'z')
			string1[i] = 'A' + string1[i] - 'a';  // 转化首字母对象,加上“相对偏移量”,即转化后的字母 
	} 
	
	for (i=0; i < len2; i++) {
		if (isalpha(string2[i]) && string2[i] >= 'a'&& string2[i] <= 'z')
			string2[i] = 'A' + string2[i] - 'a';  
	}

	// 核心算法 
	for (i=0; i < len2; i++) {
		flag = 0;
		
		for (j=0; j < len1; j++) {
			// 从字符二的i位置,比j个长度
			if (string2[i+j] == string1[j]) {
				flag = 1;  // 相等 
			} else {
				flag = 0;  // 不相等
				break;				
			} 
		}
		
		if (flag == 1) {
			// 持续匹配皆相同时
			if (string2[i+len1] == ' ' || i+len1 == count) {
				if (i == 0 || string2[i-1] == ' ') {  // i位于单词开头处 
					num ++; 
					
					if (num == 1) {
						p = i;
					} 
				}
			}
		}
	}
	
	if (num > 0) {
		// 含匹配子串
		printf("%d %d\n", num, p); 
	} else {
		printf("-1\n");
	}
	
			
//	printf("%s\n", string1);
//	printf("%s", string2);
} 
  • C++ 实现
// -*- coding: utf-8 -*-
//  @ Date   : 2021/5/20 13:14
//  @ Author : RichardLau_Cx
//  @ file   : Richard.cpp
//  @ IDE    : Dex-C++
//  @ Source : luogu

/*
	待优化:
		1. 时间复杂度较高,易超时(RE: runtime error);
		2. 个别数据未考虑周全(WA:wrong answer)。 
*/ 

#include <iostream>
#include <cstring>
#include <cmath>
#include <queue> 

using namespace std;

int main(void) {
	string word;  // 输入单词 
	string sentence;  // 输入句子 
	int wLen, sLen; 
	int j;  // 单词字母索引位置 
//	int frequency=0;  // 单词出现的频率 
	int position[99];  // 单词出现位置的数组 
	queue<int> pQ;  // 单词出现位置的队列 
	int first;  // 返回第一个位置信息 
	sentence[-1] = ' ';  // 将主串再左边的一个位置赋值为空格,便于判断 
	
//	cin >> word;
	getline(cin, word);
	getline(cin, sentence);  // 解决cin读取到空格即结束的问题 
	
//	bool temp = 
	
//	cout << "word: " << word << "  sentence[2]:---" << (sentence[2] < 'A') << "---" << endl; 
	
	wLen = word.size();  // 得到单词的长度
	sLen = sentence.length();  // 得到句子的长度 
	// 或者strlen() 
	
	for (int i=0; i < sLen; i++)
	{
		for (j=0; j < wLen; j++) 
		{
//			cout << "word[j]: " << word[j] << "  sentence[i]: " << sentence[i] << "  abs(word[j] - sentence[i]): " << abs(word[j] - sentence[i]) << endl;
			if (word[j] == sentence[i] || abs(word[j] - sentence[i]) == 32) 
			{
				// 字母相等,或者互为大小写 
//				cout << "true!" << endl;
				i++;  // 主串也相应移动 
			}
			
			else
			{
				break;
			}	
		}
		
		sentence[-1] = ' ';  //TODO 很奇怪,-1的位置为什么突然成了字母'e'了?目前只能暂时人为操作一下 
		
//		cout << "i: " << i << " i-wLen-1: " << i-wLen-1 <<  " sentence[i-wLen-1]: " << sentence[i-wLen-1] << "  sentence[i]: " << sentence[i] << endl; 
		
			
		if (j == wLen && ((sentence[i-wLen-1] < 'A') || sentence[i-wLen-1] > 'z') && ((sentence[i] < 'A') || sentence[i] > 'z'))
		{  // 单词需要完全匹配,不能是包含关系,保证前后不是字母 
			pQ.push(i-wLen);  // 将匹配到的起始位置入队 
//			frequency++; 
//			cout << "j: " << j << "  i: " << i << endl;
		 } 
		 
		else 
		{
			i -= j-1;  // 比匹配之前的位置后一个 
		}
	}
	
//	first = pQ.pop();  
	first = pQ.front();
	
	if(pQ.size()) 
	{
		cout << pQ.size() << ' ' << first << endl;
	}
	
	else
	{
		cout << -1 << endl;
	}
	
//	cout << "pQ.size(): " <<  << endl;
	
	return 0;
}
举报

相关推荐

0 条评论