这题从头到脚都散发着均摊(暴力)的气息 qwq
题意就是输入很多 ((leq 10^5))串, 维护一个 (ans) 串, 起始时 (ans) 串为空, 每输入一个串就要和 (ans) 串合并, 合并时将输入的串的最长的和 (ans) 串的某一后缀相等的前缀去掉, 然后把剩下部分接到 (ans) 串的后面。
输入串的总长不超过 (10^6)。
如果每次都暴力地将整个 (ans) 串和输入串用 (kmp) 合并, 复杂度就成了 (O(可以被卡))。
但是如果注意到去掉的输入串的前缀长度不会超过输入串的总长, 每次只截取 (ans) 的一段长为输入串长度的后缀与输入串暴力合并, 复杂度就成了均摊 (O(输入串总长)),似乎快的一批。
AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e6 + 15;
int n, ansl;
char s[maxn], ans[maxn], tmp[maxn];
int nxt[maxn];
int main()
{
cin>>n;
scanf("%s", ans+1);
ansl = strlen(ans+1);
--n;
while(n--) {
scanf("%s", s+1);
int sl = strlen(s+1);
int tmpl = min(sl,ansl);
for(int i=1;i<=tmpl;++i) tmp[i] = s[i];
for(int i=1;i<=tmpl;++i) tmp[tmpl+i] = ans[ansl-tmpl+i];
tmpl<<=1;
nxt[1]=0;
for(int i=2,j=0;i<=tmpl;++i) {
while(j&&tmp[j+1]!=tmp[i]) j=nxt[j];
if(tmp[j+1]==tmp[i]) ++j;
nxt[i]=j;
}
int mxpl = nxt[tmpl];
while(mxpl>tmpl/2) mxpl = nxt[mxpl];
int deltal = sl-mxpl;
for(int i=1;i<=deltal;++i) ans[ansl+i] = s[mxpl+i];
ansl += deltal;
}
for(int i=1;i<=ansl;++i) putchar(ans[i]);
return 0;
}