算是一道水题,但是被折腾并不幸多次贡献WA...
太久不写代码略显生疏。思路其实是有的,大体分为两种
第一种是开始尝试的,但就是这里开始不停找不到出路,不明白是何方测评神仙数据卡着,discuss里的有问题的测试数据过的都没问题。思路如下:
第二种其实是一开始方法实践之后想到的,其实方法一绕了远路,与其用AC自动机完整求出,不如直接构造两两输入字符串的“距离”矩阵:
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <deque>
using namespace std;
const int maxn= 15;
const int maxl= 25;
const int maxs= (1<<10)+5;
const int INF= 0x3f3f3f3f;
int n;
char dna[maxn][maxl];
int bd[maxn][maxn], k_next[maxn][maxl];
int lth[maxn];
int dv[maxs][maxn];
void PreKMP(char *x, int m, int *kmp_next)
{
int i, j;
i= 0;
j= kmp_next[0]= -1;
while (i< m){
while (j> -1 && x[i]!= x[j]){
j= kmp_next[j];
}
if (x[++i]== x[++j]){
kmp_next[i]= kmp_next[j];
}
else{
kmp_next[i]= j;
}
}
}
int CalcOver(int s, int t)
{
int i, j;
i= j= 0;
while (1){
while (j> -1 && dna[s][i]!= dna[t][j]){
j= k_next[t][j];
}
++i;
++j;
if (i>= lth[s]){
break;
}
if (j>= lth[t]){
j= k_next[t][j];
}
}
return j;
}
int main(int argc, char const *argv[])
{
int kase= 0;
scanf("%d", &kase);
while (kase--){
scanf("%d", &n);
for (int i= 0; i< n; ++i){
scanf(" %s", dna[i]);
lth[i]= strlen(dna[i]);
PreKMP(dna[i], lth[i], k_next[i]);
}
for (int i= 0; i< n; ++i){
for (int j= 0; j< n; ++j){
if (i== j){
bd[i][j]= lth[i];
}
else{
bd[i][j]= CalcOver(i, j);
}
}
}
const int e_mk= (1<<n)-1;
for (int i= 0; i<= e_mk; ++i){
for (int j= 0; j< n; ++j){
dv[i][j]= INF;
if (i & (1<<j)){
if (0== (i ^ (1<<j))){
dv[i][j]= lth[j];
}
else{
int ii= i ^ (1<<j);
for (int k= 0; k< n; ++k){
if (ii & (1<<k)){
dv[i][j]= min(dv[i][j], dv[ii][k]+lth[j]-bd[k][j]);
}
}
}
}
}
}
int ans= INF;
for (int i= 0; i< n; ++i){
ans= min(ans, dv[e_mk][i]);
}
printf("%d\n", ans);
}
return 0;
}
原文:https://www.cnblogs.com/Idi0t-N3/p/14961374.html