2022.02.11学习总结(kmp)

题意翻译

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;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值