185: 前缀字符串 (图,思维)

20 篇文章 0 订阅

题目地址

对于每一种关系(a是b的前缀字符串),我们可以构建出一条有向边 a->b,
把所有边连起来之后,我们可以得到一个类似于下面的图
在这里插入图片描述
会得到一个有多个连通分支的图。转换题意,使得选择某些节点,让任意的两个节点都没有连接关系,且选择的节点最多。

只需把一个连通分量中出度为0的点加入集合就可以了。因为这表示这个点不能成为所有点的前缀。
怎么保证是最多?

证明选择有出度的比没出度的更差就行。选择有出度的,则与他相连的所有点都不能被选取,会导致至少1个无出度和若干有出度的节点不能被选取,而基于构建出来图的特性,可以知道你选择有出度的 <= 选择无出度的 节点的个数。(可以自行验证)

特殊处理: 相同的字符串就没必要处理了。

#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
 
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int mod = 999911659;
const int N = 1010;

string s[N];

bool check(int i,int j){
	if((int)s[i].size() >= (int)s[j].size()) return false;
	return s[i] == (s[j].substr(0,(int)s[i].size()));
}

signed main(){
//	IOS;
	#ifdef ddgo
		freopen("C:/Users/asus/Desktop/ddgoin.txt","r",stdin);
	#endif
	
	int n;
	while(cin>>n && n){
		map<string,int> mp,mp1;
		int cnt = 0;
		for(int i=0;i<n;i++){
			string p; cin>>p;
			if(!mp[p]) s[cnt++] = p,mp[p] = 1;
		}
		for(int i=0;i<cnt;i++) //连边,标记有出度的
			for(int j=0;j<cnt;j++){
				if(i == j) continue;
				if(check(i,j)) mp1[s[i]] = 1;
			}
		int res = 0;
		for(int i=0;i<cnt;i++) res += (mp1[s[i]]?0:1);
		cout<<res<<endl;
	}
	
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值