码迷,mamicode.com
首页 > 其他好文 > 详细

[CF1200E] Compress Words - KMP

时间:2020-04-04 00:18:27      阅读:50      评论:0      收藏:0      [点我收藏+]

标签:with   +=   ios   class   fail   space   相等   sub   lse   

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

Solution

前缀配后缀,想到 KMP

每次构造一个待匹配串在前,已匹配串在后的串,计算这个串最后一位的 \(next\) 值就是本次匹配的宽度

注意已匹配串的长度最多只需要截取到待匹配串的长度即可

#include <bits/stdc++.h>
using namespace std;

const int N = 1000005;

int fail[N];
char p[N];

void calc(int m) {
    for(int i=0;i<=m+1;i++) fail[i]=0;
    for(int i=2;i<=m;i++) {
		fail[i]=fail[i-1];
		while(p[fail[i]+1]-p[i] && fail[i]) fail[i]=fail[fail[i]];
		if(p[fail[i]+1]==p[i]) ++fail[i];
	}
	for(int i=0;i<=m+1;i++) p[i]=0;
}

int n;
string s[N],ans,tmp;

signed main() {
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>s[i];
    for(int i=1;i<=n;i++) {
        tmp.clear();
        tmp+=s[i];
        tmp+="$";
        tmp+=ans.substr(max(0,(int)(ans.length()-s[i].length())));
        for(int i=1;i<=tmp.length();i++) p[i]=tmp[i-1];
        calc(tmp.length());
        ans+=s[i].substr(fail[tmp.length()]);
    }
    cout<<ans;
}

[CF1200E] Compress Words - KMP

标签:with   +=   ios   class   fail   space   相等   sub   lse   

原文地址:https://www.cnblogs.com/mollnn/p/12629413.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!