UVA10391 UVA10391 复合词 Compound Words 题解

提示:萌新不会写substr,所以本篇是适合新手阅读的题解。

PART 01 读入

我们可以利用C++语言的特性,把字符串读入写入循环条件里:

for( ; cin>>s[cnt] ; ){ //C++语言特性
	cnt++;
}

为了避免变量重名,也为了为字符串数组提供指针,用 cnt 表示目前读入的下标,而最终的 cnt 就是字符串的数量。

PART 02 算法

2.1:字符串匹配

我们知道判断一个字符串是否是复合串的方法就是将其分成两半,然后再分别判断分出来的两个字符串是否存在。因此我们可以使用 map 来存储字符串是否存在过

map <string,bool> p;
for( ; cin>>s[cnt] ; ){
	p[s[cnt]] = true; //如果该字符串存在了,map 值变为 true
	cnt++;
}

2.2:隔板法

如果我们想要把一个字符串分成两个部分,可以理解为将一个整体用一块隔板将其分开。所以不妨用一个循环变量当做隔板进行字符串分割。

for(int j = 1 ; j < s[i].length() ; j++){ // j 作为隔板分割字符串
		for(int k = 0 ; k < j ; k++){
			a += s[i][k]; // j 前面的字符都变成前半部分的串(a)
		}
		for(int k = j ; k < s[i].length() ; k++){
			b += s[i][k]; // j 后面的字符都变成后半部分的串(b)
		}
}

注意,有些同学认为当存在两个相同的串时,也认为其中一个是复合串,但其实这样的串也属于普通串的范畴。因此,我们可以发现 b 串至少可以取到最后一个字符,排除了有相同串的情况

2.3:判断情况

这里便可以体现出 map 的作用。

只要得到了 a 串与 b 串我们就可以往循环里面加入判断,即通过 map 的布尔值来判断是否存在过。

for(int j = 1 ; j < s[i].length() ; j++){
		for(int k = 0 ; k < j ; k++){
			a += s[i][k];
		}
		for(int k = j ; k < s[i].length() ; k++){
			b += s[i][k];
		}
		if(p[a] && p[b]){
			cout<< s[i] <<endl;
			break; //就是这里,如果不加就会WA掉,因为可能一个串有多种分割办法。
		}
}

值得一提的是,为了防止拼法有多种导致多种输出,有必要在判断完后进行 break 。

最后要记住,清空 A 串与 B 串以供下次使用。

AC代码

AC记录

#include <bits/stdc++.h>
using namespace std;
map <string,bool> p;
string s[120030],a,b;
int cnt;
int main(){
	for( ; cin>>s[cnt] ; ){
		p[s[cnt]] = true;
		cnt++;
	}
	for(int i = 0 ; i < cnt ; i++){
		for(int j = 1 ; j < s[i].length() ; j++){
			a = "";
			b = "";
			for(int k = 0 ; k < j ; k++){
				a+=s[i][k];
			}
			for(int k = j ; k < s[i].length() ; k++){
				b+=s[i][k];
			}
			if(p[a] && p[b]){
				cout<< s[i] <<endl;
				break;
			}
		}
	}
	return 0;
}
上一篇:A Surface Defect Detection Method Based on Positive Samples


下一篇:974. 和可被 K 整除的子数组