bzoj3207 Orthogonal Anagram 贪心+Hall定理

33 篇文章 0 订阅
3 篇文章 0 订阅

Description


一个字符串的变形词是一个字符串,它含有恰好完全一样的字母,可能以不同的顺序出现。例如,\porter",\report"和\eoprrt"都是\porter"的变形词。而\potter"不是它的变形词,因为\t"和\r"出现的次数不同。

字符串S和T是正交的,当且仅当它们长度相同,而且每个对应位都不同。例如,\card"和\dear"是正交的,而\perk"和\card"不是正交的,因为它们的第3个字母相同。

给出一个字符串S,求S的字典序最小的正交变形词。如果这样的字符串不存在,就让答案是空串。

Solution


早上想了一个正解贪心结果不会证明不太敢写。。

我们从小到大枚举当前位置填上的字符,后面是否能填用网络流判断。原点向字符连边容量为可用数量,每个字符向能放的位置连边容量为1,位置向汇点连边容量为1,那么剩余能放完当且仅当满流。我们把容量为x的边拆成x条容量为1的边,那么就变成存在完美匹配了

我们只需要证明最劣情况下它是合法的。对于不同的两个字符,它们连出去的边覆盖的点集一定是全集。对于相同的若干字符,它们连出去的边覆盖的点集不变,因此我们只需要比较每类字符能放的位置/剩余的数量即可。

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)

const int N=200005;

char s[N],t[N];

int a[26],b[26],c[26];

int main(void) {
	scanf("%s",s+1); int n=strlen(s+1);
	rep(i,1,n) a[s[i]-'a']++,b[s[i]-'a']++;
	rep(i,'a','z') {
		rep(j,'a','z') if (i!=j) {
			c[i-'a']+=a[j-'a'];
		}
	}
	rep(i,1,n) {
		t[i]=1;
		rep(j,'a','z') if (j!=s[i]&&a[j-'a']) {
			a[j-'a']--;
			rep(k,'a','z') if (s[i]!=k) c[k-'a']--;
			bool flag=true;
			rep(k,'a','z') if (a[k-'a']>c[k-'a']) flag=false;
			if (flag) {
				t[i]=j;
				break;
			}
			a[j-'a']++;
			rep(k,'a','z') if (s[i]!=k) c[k-'a']++;
		}
		if (t[i]==1) {
			puts("");
			return 0;
		}
	}
	rep(i,1,n) putchar(t[i]); puts("");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值