题目链接:https://codeforces.ml/contest/1200/problem/E
题意:给定一些单词,总长度不超过1e6。如果后缀与前缀匹配就只需要保留一个,例如,
input:::
5
sample please ease in out
outpur:::
sampleaseinout
题解:直接暴力过了12个点。思考kmp怎么做,很明显的kmp,只要方法是正确的,就一定能找到答案。
如please-ease.只需要求出ease#ease(如果ans长度小于s即"ease"的长度,那么截取所有即可)的最大前缀函数。然后只保留一段。
总结:时间复杂度大概再O(2^n)
代码:
#include <bits/stdc++.h>
#define ll int
#define pi acos(-1)
#define pb push_back
#define mst(a, i) memset(a, i, sizeof(a))
#define pll pair<ll, ll>
#define fi first
#define se second
#define mp(x,y) make_pair(x,y)
#define dbg(x) cout << #x << "===" << x << endl
#define rep(i,a,n) for(ll i=a;i<=n;i++)
using namespace std;
template<class T>void read(T &x){T res=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){res=(res<<3)+(res<<1)+c-'0';c=getchar();}x=res*f;}
void print(ll x){if(x<0){putchar('-');x=-x;}if(x>9)print(x/10);putchar(x%10+'0');}
const ll maxn = 1e6 + 10;
const ll mod = 1e9 + 7;
ll n,ls,lans;
char s[maxn],ans[maxn];
ll a[maxn],p;
void add(){
ll t=min(lans,ls);
a[0]=0;
s[ls++]='#';//?注意
rep(i,1,ls-1){
p=a[i-1];
while(p>0&&s[i]!=s[p]) p=a[p-1];
p+=(s[i]==s[p]);
a[i]=p;
}
--ls;//?褪去'#'
ll x=ls;
rep(i,lans-t,lans-1){
++x;
p=a[x-1];
while(p>0&&ans[i]!=s[p]) p=a[p-1];
p+=(ans[i]==s[p]);
a[x]=p;
}
rep(i,a[x],ls-1) ans[lans++]=s[i];
// dbg(ans);
}
/*
?暴力写法
void add(){
ll f=0,i,j,k;
for(i=max(0,lans-ls);i<lans;i++){
if(ans[i]-'0'!=s[0]-'0') continue;
f=1;
for(k=0,j=i;j<lans;j++,k++){
if(ans[j]-'0'!=s[k]-'0'){
f=0;break;
}
}
if(f) break;
}
//dbg(f);
if(!f) k=0;
for(i=k;i<ls;i++) ans[lans++]=s[i];
}
*/
//ll gcd(ll a,ll b){return (b==0)?a:gcd(b,a%b);}
ll qpow(ll a,ll p,ll mod){ll ans=1;a=a%mod;while(p){if(p&1)ans=(ans*a)%mod;p>>=1;a=(a*a)%mod;}return ans;}
int main() {
ll _s = 1;
//read(_s);
for (ll _=1;_<=_s;_++) {
read(n);
for(ll i=1;i<=n;i++){
scanf("%s",s);
// cout<<s<<endl;
ls=strlen(s);
add();
}
printf("%s",ans);
}
return 0;
}