题意翻译
Amugae有n个单词,他想把这个n个单词变成一个句子,具体来说就是从左到右依次把两个单词合并成一个单词.合并两个单词的时候,要找到最大的i(i\ge 0)i(i≥0),满足第一个单词的长度为ii的后缀和第二个单词长度为ii的前缀相等,然后把第二个单词第ii位以后的部分接到第一个单词后面.输出最后那个单词
输入输出样例
输入 #1复制
5 I want to order pizza输出 #1复制
Iwantorderpizza输入 #2复制
5 sample please ease in out输出 #2复制
sampleaseinout
看到这个题,我第一感觉就是跟那个奶牛的题有点像,于是思路也很快出来了,两两单词连接,推导next数组,求最大相同前后缀,然后再进行字符串的裁剪,再添加到总字符串里就可以,于是这样一篇代码就出来了。
#include<bits\stdc++.h>
using namespace std;
int N[1000002];
void GetNext(string s)
{
int i=0,k=-1;
N[0]=-1;
while(i<=s.length()-1){
if(k==-1||s[i]==s[k]){
i++;k++;N[i]=k;
}else k=N[k];
}
}
int main()
{
int n;
cin>>n;
string s,ss,ch,str;
getchar();
cin>>ch;
for(int j=2;j<=n;j++){
cin>>str;//cin输入不能输入空格
s=str+ch;//前一字符串和当前输入字符串组合
//cout<<str<<endl<<s;
for(int i=1;i<=s.length();i++){
GetNext(s);}
ch.erase(ch.length()-N[s.length()]);
ss=ss+ch;ch=str;
}ss=ss+ch;
cout<<ss;
}
但是我想的还是太简单了,毕竟人家可是提高+的题emmm,交上去一直时间超限,为了让时间更快点,我们可以对要进行next数组推导的字符串进行裁剪,就是不可能包含在相同前后缀的字符们不推导next数值,然后为了避免next数值跨越两个不同的字符串,我们可以在两者之间加入非字母的字符,优化后的代码如下。
#include<bits\stdc++.h>
using namespace std;
int N[1000002];
void GetNext(string s)//推导next数组
{
int i=0,k=-1;
N[0]=-1;
while(i<=s.length()-1){
if(k==-1||s[i]==s[k]){
i++;k++;N[i]=k;
}else k=N[k];
}
}
int main()
{
int n;
cin>>n;
string ch,str;
getchar();
cin>>ch;
for(int j=2;j<=n;j++){
//if(j!=n){
cin>>str;//cin输入不能输入空格
int l=min(str.length(),ch.length());//取两者长度较小值
string s=str+"%"+ch.substr(ch.length()-l,l);/*将前面的字符串和当前输入的字符串进行组合,
为了提高速度,我们可以将要组合的ch字符串进行裁剪,只选等于str字符串长度的部分,中间可以加入一些非字母的字符,防止next数组跨越两个不同的字符串*/
//for(int i=1;i<=s.length();i++){
GetNext(s);
//ch.erase(ch.length()-N[s.length()]);
//ch=ch+str.substr(N[s.length()],str.length());
for(int i=N[s.length()];i<str.length();i++){//添加字符
ch+=str[i];
}
}
cout<<ch;
}