noi.ac #546 分组

题目链接:戳我

题目描述

现在有n个字符串,你需要从中选出一些字符串,使得选出的字符串能被分组,满足每组大小为2,且可以从每组选出该组的两个字符串的一个非空公共后缀,使得每组选出的串互不相同。

输入格式

第一行一个整数n。
接下来n行,每行一个字符串。

输出格式

输出一个整数,表示答案。

样例输入

2
TARPOL
PROL

样例输出

2

数据范围

对于所有数据,1≤n≤5000,|Si|≤50,其中|Si| 表示输入的第i个字符串的长度。
时间限制 1s1s ,空间限制 512MB。
subtask1(20pts):n≤2。
subtask2(20pts):n≤6。
subtask3(20pts):n≤10。
subtask4(20pts):n≤100。
subtask5(20pts): 无特殊限制。

把所有的串反过来,建字典树。然后每一个节点最多取2个,从深到浅贪心即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 5010
int n,tot,len;
int f[MAXN*55],ch[MAXN*55][27];
char s[55];
inline void dfs(int x)
{
	for(int i=0;i<26;i++)
	{
		if(ch[x][i]) 
			dfs(ch[x][i]),f[x]+=f[ch[x][i]];
	}
	if(x&&f[x]>=2) f[x]-=2;
}
int main()
{
	#ifndef ONLINE_JUDGE
	freopen("ce.in","r",stdin);
	#endif
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		len=strlen(s+1);
		int now=0;
		for(int j=len;j>=1;j--)
		{
			if(!ch[now][s[j]-'A']) ch[now][s[j]-'A']=++tot;
			now=ch[now][s[j]-'A'];
		}
		f[now]++;
	}
	dfs(0);
	printf("%d
",n-f[0]);
	return 0;
}
原文地址:https://www.cnblogs.com/fengxunling/p/11163866.html