abc 343

G Compress Strings

思路

  • 一眼状压(n 只有 20)

  • 分类讨论

    • 如果 s[i] 包含了 s[j], 就没有 s[j] 什么事了
    • 否则考虑 i 加到 j 后面和反过来的代价
      • 就是求 i+j 的 border
  • 上述两个过程都可以 KMP 解决

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int M = 1.5e6 + 10;
const int N = 25;
int n;
int nxt[M], dp[M][N];
int cost[N][N], si;
string s[N];
set <int> str;
int Kmp(string s){
for(int i = 0; i < s.size(); i++){
nxt[i] = 0;
}
int j = 0;
for(int i = 1; i < s.size(); i++){
while(j && s[i] != s[j]){
j = nxt[j - 1];
}
if(s[i] == s[j]){
j++;
}
nxt[i] = j;
if(nxt[i] == si){
return si;
}
}
return nxt[s.size() - 1];
}
signed main(){
// freopen("1.in", "r", stdin);
cin >> n;
for(int i = 1; i <= n; i++){
cin >> s[i];
str.insert(i);
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(s[i].size() > s[j].size() || i == j || str.find(j) == str.end()){
continue;
}
si = s[i].size();
if(s[i].size() == Kmp(s[i]+'#'+s[j])){
// cout << i << "i ";
str.erase(i);
}
}
}
memset(dp, 0x3f3f3f3f, sizeof(dp));
int cnt = 0;
si = -1;
for(auto i : str){
for(auto j : str){
int ret = s[j].size() - Kmp(s[j]+"#"+s[i]);
cost[i][j] = ret;
}
dp[1<<cnt][cnt] = s[i].size();
cnt++;
}
int up = (1 << str.size()) - 1;
for(int i = 0; i <= up; i++){
int cnt = 0;
for(auto j : str){
if(!((i >> cnt) & 1)){
++cnt;
continue;
}
int cntt = 0;
for(auto k : str){
if((i >> cntt) & 1){
cntt++;
continue;
}
dp[i|(1<<cntt)][cntt] = min(dp[i|(1<<cntt)][cntt], dp[i][cnt] + cost[j][k]);
cntt++;
}
++cnt;
}
}
int mini = (int)1e18;
for(int i = 0; i < str.size(); i++){
// cout << dp[up][i] << " ";
mini = min(mini, dp[up][i]);
}
cout << mini << "\n";
}
posted on   Bubble_e  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话



点击右上角即可分享
微信分享提示