提示:萌新不会写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代码
#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;
}