题目描述
最长公共子序列 + Kruskal
C++ 代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int n, m;
const int N = 210;
string str[N];
vector<pair<int,pair<int, int>>>vec;
int dp[N][N];
int solveD(string A, string B)
{
int res = 0;
/*
aabbaabb
abbaabba
accaacca
*/
memset(dp, 0 ,sizeof dp);
for (int i = 1; i < A.size(); i ++)
{
for (int j = 1; j < B.size(); j ++)
{
if ( A[i - 1] == B[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
res = max(dp[i][j],res);
}
}
}
res = min(res, m);
return res;
}
int p[N];
int find(int x) // 并查集
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i ++) {
cin >> str[i];
str[i] = str[i] + str[i];
}
for (int i = 1;i <= n;i ++){
p[i] = i;
}
for (int i = 0;i < n;i ++)
{
for (int j = i + 1;j < n;j ++) {
int d = solveD(str[i],str[j]);
// cout << d << endl;
vec.push_back({d, {i, j}});
}
}
sort(vec.begin(),vec.end(),[](pair<int,pair<int,int>>p1, pair<int,pair<int,int>>p2){
return p1.first > p2.first;
});
int res = 0;
for (int i = 0; i < vec.size();i ++)
{
int a = vec[i].second.first, b = vec[i].second.second;
int p1 = find(a), p2 = find(b);
if (p1 != p2) {
res += vec[i].first;
p[p2] = p1;
}
}
cout << res << endl;
return 0;
}