7-3 接话茬 (100分)
小CC最喜欢的就是接话茬,别人说一句,小CC就会接着他的话尾巴继续说下去,然后告诉他这是“顶针”修辞手法,活活将人气死。小XX也喜欢接话茬,每天都要与小CC比较技艺。然而无论是谁,都会被他们活活气死,因此两人总是难决胜负。后来小CC和小XX一起上了厦门大学,学习了校选课《接话茬数学原理与杠精的自我修养》,他们决定对两人的接话茬水平进行定量评估。
他们约定比赛规则如下,随机找一个倒霉的路人,路人说一句话,他们一起来接,他们接的话的前缀可以作为路人说的话后缀的长度就是那句话的水平。比如,别人说“abbbaabbc”,小CC接了一句“abbcefagd”,他所说的话的前缀“abbc”正是路人所说的话的后缀,长度为4,那么小CC的水平就是4;如果小XX说的是“xbbcadf”,无法构成路人所说的话的后缀,因此水平只有0。
现在,他们的比赛正式开始,由你来写一个程序充当裁判。
输入格式:
共三行,每行是一句话,长度均不超过10
6
。
第一行是路人说的话。第二行是小CC说的话。第三行是小XX说的话。
输出格式:
仅一行,输出小CC和小XX接的话的水平,以空格分割,行末没有多余空格,以换行结束。
输入样例:
abbaabbc
abbc
xbb
输出样例:
4 0
初级版本
这个版本的代码比较容易想到。但是过测试点的时候随机长串这一测试点过不了。
原因在于在获得得分代码编写的时候,前后缀的长度是从i开始(也就是1),也就是说需要遍历完整个for循环,最后得到的分数才是最大长度。
当字符串过于长的时候,显然,运行时间得不到满足。
#include<iostream>
#include<string>
using namespace std;
int main(){
string passer,cc,xx;//分别记录路人cc,xx的话
cin>>passer>>cc>>xx;
int min_pc=passer.size()>cc.size()?cc.size():passer.size();//记录路人和cc的最小长度
int min_px=passer.size()>xx.size()?xx.size():passer.size();//记录路人和xx的最小长度
int score_cc,score_xx;//记录cc和xx的得分(即它们前缀能匹配到路人的后缀的最长长度)
//计算cc的得分
for(int i=1;i<=min_pc;i++){
string c=cc.substr(0,i);//截取cc长度为i的前缀
string p=passer.substr(passer.size()-i,i);//截取路人长度为i的后缀
if(c==p){
score_cc=i;
}
}
//计算xx的得分
for(int i=1;i<=min_px;i++){
string x=xx.substr(0,i);//截取xx长度为i的前缀
string p=passer.substr(passer.size()-i,i);//截取路人长度为i的后缀
if(x==p){
score_xx=i;
}
}cout<<score_cc<<" "<<score_xx;
}
修改版本
那可不可以加一个什么条件让尽早退出for循环并找到最大长度呢?
很简单。只需要将i从最大值依次递减遍历即可。当满足if中的条件时即可跳出。
请看下面的实现:
#include<iostream>
#include<string>
using namespace std;
int main(){
string passer,cc,xx;//分别记录路人cc,xx的话
cin>>passer>>cc>>xx;
int min_pc=passer.size()>cc.size()?cc.size():passer.size();//记录路人和cc的最小长度
int min_px=passer.size()>xx.size()?xx.size():passer.size();//记录路人和xx的最小长度
int score_cc,score_xx;//记录cc和xx的得分(即它们前缀能匹配到路人的后缀的最长长度)
//计算cc的得分
for(int i=min_pc;i>0;i--){
string c=cc.substr(0,i);//截取cc长度为i的前缀
string p=passer.substr(passer.size()-i,i);//截取路人长度为i的后缀
if(c==p){
score_cc=i;
break;//如果满足,直接跳出
}
}
//计算xx的得分
for(int i=min_px;i>0;i--){
string x=xx.substr(0,i);//截取xx长度为i的前缀
string p=passer.substr(passer.size()-i,i);//截取路人长度为i的后缀
if(x==p){
score_xx=i;
break;//如果满足,直接跳出
}
}cout<<score_cc<<" "<<score_xx;
}