CF1200E Compress Words(KMP)

题意:

Amugae有n个单词,他想把这个n个单词变成一个句子,具体来说就是从左到右依次把两个单词合并成一个单词.合并两个单词的时候,要找到最大的i(i\ge 0)i(i≥0),满足第一个单词的长度为ii的后缀和第二个单词长度为ii的前缀相等,然后把第二个单词第ii位以后的部分接到第一个单词后面.输出最后那个单词。

题解:

这题事实上要我们求的是:

当前拼接好的串的后缀 和 待拼接串的前缀最大匹配长度

可能有点绕,我们结合样例2来理解下。

当前拼接好的串 samplesample

待拼接串 pleaseplease

后缀和前缀的最大匹配 pleple

最大匹配长度 33

所以我们只要把 asease 加入到当前拼接好的串。

此时当前拼接好的串 sampleasesamplease

那么匹配的工作就交给KMP啦;

上板子:(小蓝书上的)


//char a[],b[],int next1[],lb=strlen(b+1),la=strlen(a+1);
void KMP(){
    next1[1]=0;
    for(int i=2,j=0;i<=lb;i++) 
    {
        while(j!=0&&b[i]!=b[j+1])
        j=next1[j];
        if(b[i]==b[j+1])j++;
        next1[i]=j;
    }
}
void get_f(){
	for(int i=1,j=0;i<=la;i++){
		while(j>0&&(a[i]!=b[j+1])) 
		j=next1[j];
		if(a[i]==b[j+1])
			j++;
		if(j==lb){
		j=next1[j];
		printf("%lld\n",i-lb+1); 
	}
}
}

完整代码如下:

/*Keep on going Never give up*/
#include <bits/stdc++.h>
using namespace std;
#define MAX 0x7fffffff
#define int long long
const int mod = 1e9+7;
const int maxn = 1e6+1000;
char a[maxn],ans[maxn];
int n,next1[maxn],anslen,mi,top;
int KMP(){
    next1[1]=0;
    for(int i=2,j=0;i<=top;i++) 
    {
        while(j!=0&&a[i]!=a[j+1])
        j=next1[j];
        if(a[i]==a[j+1])j++;
        next1[i]=j;
    }
    return next1[top];
}
signed main(){
	scanf("%lld",&n);
	for(int k=1;k<=n;k++){
		scanf("%s",a+1);
		int len=strlen(a+1);
		top=len;
		a[++top]='#';// 避免匹配到超出原串的字符;
		mi=min(len,anslen);
		for(int i=1;i<=mi;i++)a[++top]=ans[anslen-mi+i];
		int ll=KMP();
		for(int i=ll+1;i<=len;i++)ans[++anslen]=a[i];
	}
	for(int i=1;i<=anslen;i++)printf("%c",ans[i]);
	return 0;
}		

结束啦:)

div2的E题也很简单嘛(小声bb)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值