jzoj 3207.【HNOI模拟题】Orthogonal Anagram 霍尔定理+贪心
作者:互联网
Description
一个字符串的变形词是一个字符串,它含有恰好完全一样的字母,可能以不同的顺序出现。例如,\porter",\report"和\eoprrt"都是\porter"的变形词。而\potter"不是它的变形词,因为\t"和\r"出现的次数不同。
字符串S和T是正交的,当且仅当它们长度相同,而且每个对应位都不同。例如,\card"和\dear"是正交的,而\perk"和\card"不是正交的,因为它们的第3个字母相同。
给出一个字符串S,求S的字典序最小的正交变形词。如果这样的字符串不存在,就让答案是空串。
Input
仅一行,一个字符串S。
Output
仅一行,表示答案。
Sample Input
abba
Sample Output
baab
Data Constraint
有10%数据,字符串长度不超过10。
另有10%数据,恰有2种不同的字母。
另有20%数据,只有不超过5种不同的字母。
对于80%数据,字符串长度不超过50。
对于100%数据,字符串长度不超过50000,所有字符都是小写拉丁字母。
分析:
我们把第一个串的字母对第二个串字母进行匹配,显然合法匹配就是两两不相同。
匹配建图就是每个字母向它的不同字母连边。
显然根据这个二分图的特殊性质,根据霍尔定理,左边如果选了两个不同字母,对应右边一定是全集,一定符合。所以左边选尽量多的相同字母,如果都能满足就存在完全匹配。
设suml[i]表示字母i在左边的个数,sumr[i]表示字母i在右边的个数,d为带匹配的总字母数。
如果存在完全匹配,那么∀i∈[a,z]suml[i]<=d−sumr[i]。
对于每一位贪心求,暴力枚举每一个字母,判断选了之后是否存在完全匹配即可。
复杂度是O(262len)。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
const int maxn=50007;
using namespace std;
int n,l;
int numl[30],numr[30];
char s[maxn];
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
for (int i=1;i<=n;i++)
{
numl[s[i]-'a']++;
numr[s[i]-'a']++;
}
int flag=0;
for (int i=0;i<26;i++)
{
if (numl[i]>n-numr[i])
{
flag=1;
break;
}
}
if (flag==1) return 0;
l=n;
for (int i=1;i<=n;i++)
{
numl[s[i]-'a']--;
l--;
for (int j=0;j<26;j++)
{
if ((s[i]-'a'==j) || (!numr[j])) continue;
flag=0;
numr[j]--;
for (int k=0;k<26;k++)
{
if (numl[k]>l-numr[k])
{
flag=1;
break;
}
}
if (!flag)
{
printf("%c",'a'+j);
break;
}
else numr[j]++;
}
}
}
标签:3207,匹配,Orthogonal,int,字母,sumr,模拟题,suml,字符串 来源: https://blog.csdn.net/liangzihao1/article/details/86682055