https://codeforces.com/contest/1200/problem/E
题意:给出n个单词,可以把每个单词前缀后缀相同的部分合并,求最后合并单词
kmp模板题… 比赛的时候自己没有模板,网上随便找了个模板,改到最后tle,没有时间了,原因还是因为记不清楚kmp算法了,通过这道题复习了下。
思路:从第二个开始字符串开始和前面合并的子串进行kmp算法
注意每次匹配的起点位置,应该为 文本串长度-模式串长度
#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define fi first
#define se second
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, int> LP;
const ll inf = 1e17 + 10;
const int N = 1e6 + 100;
const ll mod = 10007;
const int base=131;
tr1::unordered_map<ll,ll> mp;
char a[N],b[N],ans[N];
int nx[N];
int n, m;
int l1,l2;
void getnext(){
int k = -1, j = 0;
nx[0] = -1;
while(j < m){
if(k == -1 || b[j] == b[k]) nx[++j] = ++k;
else k = nx[k];
}
}
int KMP(int st)
{
int i,j;
getnext();
for(i=st,j=0;i<n;i++)
{
while(j>0&&b[j]!=a[i]) j=nx[j];//匹配不成功 跳转到nx
if(a[i]==b[j]) j++;
if(j==m) return m;
}
return j;
}
int main()
{
int t;
scanf("%d",&t);
scanf("%s",a);
n=strlen(a);
t--;
int pos=0;
for(int i=1;i<=t;i++)
{
scanf("%s",b);
m=strlen(b);
int x=KMP(max(pos-m,0));
//show2(i,x)
for(int i=x;i<m;i++)
{
a[n++]=b[i];
}
pos=n;
}
a[n]='\0';
printf("%s\n",a);
}