3 ab bcc ccb 1 abcd
6 0
思路:
裸的KM,建图后直接用模板就够了,注意是“longest common prefix”,题目不要读错了。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> //#pragma comment (linker,"/STACK:102400000,102400000") #define maxn 205 #define MAXN 1000005 #define mod 1000000007 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 typedef long long ll; using namespace std; int n,nx,ny,ans; int link[maxn],lx[maxn],ly[maxn],slack[maxn]; //lx,ly为顶标,nx,ny分别为x点集y点集的个数 int visx[maxn],visy[maxn],w[maxn][maxn]; int len[maxn]; char s[maxn][1005]; int DFS(int x) { visx[x] = 1; for (int y = 1;y <= ny;y ++) { if (visy[y]) continue; int t = lx[x] + ly[y] - w[x][y]; if (t == 0) { visy[y] = 1; if (link[y] == -1||DFS(link[y])) { link[y] = x; return 1; } } else if (slack[y] > t) //不在相等子图中slack 取最小的 slack[y] = t; } return 0; } int KM() { int i,j; memset (link,-1,sizeof(link)); memset (ly,0,sizeof(ly)); for (i = 1;i <= nx;i ++) //lx初始化为与它关联边中最大的 for (j = 1,lx[i] = -INF;j <= ny;j ++) if (w[i][j] > lx[i]) lx[i] = w[i][j]; for (int x = 1;x <= nx;x ++) { for (i = 1;i <= ny;i ++) slack[i] = INF; while (1) { memset (visx,0,sizeof(visx)); memset (visy,0,sizeof(visy)); if (DFS(x)) break; int d = INF; for (i = 1;i <= ny;i ++) if (!visy[i]&&d > slack[i]) d = slack[i]; for (i = 1;i <= nx;i ++) if (visx[i]) lx[i] -= d; for (i = 1;i <= ny;i ++) //修改顶标后,要把所有不在交错树中的Y顶点的slack值都减去d if (visy[i]) ly[i] += d; else slack[i] -= d; } } int res = 0; for (i = 1;i <= ny;i ++) if (link[i] > -1) res += w[link[i]][i]; return res; } void presolve() { int i,j,k,p1,p2,cnt; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(i==j) { w[i][j]=0; continue ; } cnt=0; p1=len[i]-1; p2=0; while(1) { if(s[i][p1]==s[j][p2]) cnt++; else break ; p1--,p2++; if(p1<0||p2>=len[j]) break ; } w[i][j]=cnt; } } } int main() { int i,j; while(~scanf("%d",&n)) { nx=ny=n; for(i=1;i<=n;i++) { scanf("%s",s[i]); len[i]=strlen(s[i]); } presolve(); ans=KM(); printf("%d\n",ans); } }