于是你把我给杀死了
考虑 dp,
- 长串仍然更长,
f_{i, j} \leftarrow f_{i, j - t} - 短串更长了,
f_{i, j} \leftarrow f_{k, len_{k} - j} , 不懂的可以画一下,比较显然。
转移有环怎么办?由于是求最小值,所以直接将转移建边,跑最短路即可。
时间复杂度
吗?
如果是这样,那过不了加强版,但是加强版跑的飞快,为什么?
dijkstra 的时间复杂度为
时间复杂度
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 60, M = 2510, mod = 998244353;
template<typename T>
void dbg(const T &t) { cout << t << endl; }
template<typename Type, typename... Types>
void dbg(const Type& arg, const Types&... args) {
cout << arg << ' ';
dbg(args...);
}
int n, m, tot, id[N][N], f[M], len[N];
string s[N];
vector<pii>e[M];
int main() {
// freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> s[i];
len[i] = (int)s[i].size();
for (int j = 0; j < len[i]; j++) id[i][j] = ++tot;
}
for (int i = 1; i <= n; i++)
for (int j = 0; j < len[i]; j++)
for (int k = 1; k <= n; k++) {
int t = min(len[k], j);
if (s[k].substr(0, t) == s[i].substr(len[i] - j, t)) {
if (j < len[k]) {
e[id[i][j]].push_back({id[k][len[k] - j], t});
} else {
e[id[i][j]].push_back({id[i][j - t], len[k]});
}
}
}
memset(f, 0x3f, sizeof f);
set<string>st; priority_queue<pii, vector<pii>, greater<pii>>q;
for (int i = 1; i <= n; i++) st.insert(s[i]);
for (int i = 1; i <= n; i++) {
for (int j = 1; j < len[i]; j++) {
string t = s[i].substr(0, j);
if (st.count(t)) {
f[id[i][len[i] - j]] = j;
q.push({j, id[i][len[i] - j]});
}
}
}
while (!q.empty()) {
auto [dis, u] = q.top(); q.pop();
if (f[u] != dis) continue;
for (auto [v, w] : e[u]) {
if (f[v] > f[u] + w) {
f[v] = f[u] + w;
q.push({f[v], v});
}
}
}
int ans = 0x3f3f3f3f;
for (int i = 1; i <= n; i++) ans = min(ans, f[id[i][0]]);
cout << (ans == 0x3f3f3f3f ? -1 : ans) << '\n';
return 0;
}
结束了吗?没有。
可以把堆换成桶,时间复杂度