#include <bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int N = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int P = 13331;
inline int read() {
int f = 1, x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + (ch - '0');
ch = getchar();
}
return f * x;
}
int n;
string s[N], ans;
ull Hash0[N], Hash1[N];
ull p[N];
ull GetHash(int l, int r, int k) {
if (!k) return Hash0[r] - Hash0[l - 1] * p[r - l + 1];
return Hash1[r] - Hash1[l - 1] * p[r - l + 1];
}
int Solve(int k) {
int len1 = s[k].size();
int len2 = s[k - 1].size();
if (k != 2) for (int i = 0; i < len1; i++) Hash0[i] = Hash1[i];
for (int i = 0; i < len1; i++) Hash1[i] = Hash1[i - 1] * P + s[k][i];
int mlen = min(len1, len2);
for (int len = mlen ; len >= 0; len--) {
// if (k == 2) {
// cout <<"len="<<len<<" "<< GetHash(len2 - len, len2, 0)<<' '<< GetHash(0, len - 1, 1)<<"\n";
// }
if (GetHash(len2 - len, len2, 0) == GetHash(0, len - 1, 1)) {
return len;
}
}
return -1;
}
signed main() {
n = read();
p[0] = 1;
for (int i = 1; i <= N; i++) p[i] = p[i - 1] * P;
cin >> s[1];
ans += s[1];
for (int i = 0; i < s[1].size(); i++) Hash0[i] = Hash0[i - 1] * P + s[1][i];
for (int i = 2; i <= n; i++) {
cin >> s[i];
int len = Solve(i);
// cout << len <<"\n";
// cout << GetHash(s[i - 1].size() - 1 - 2, s[i - 1].size(), 0) << " " << GetHash(0, 2, 1) << "\n";
if (len == -1) {
ans += s[i];
continue;
}
for (int j = len; j < s[i].size(); j++) ans += s[i][j];
}
cout << ans;
return 0;
}
调了2h时了,感觉写的很合理,很清楚但是样例都没过