Description
一个字符串的变形词是一个字符串,它含有恰好完全一样的字母,可能以不同的顺序出现。例如,\porter",\report"和\eoprrt"都是\porter"的变形词。而\potter"不是它的变形词,因为\t"和\r"出现的次数不同。
字符串S和T是正交的,当且仅当它们长度相同,而且每个对应位都不同。例如,\card"和\dear"是正交的,而\perk"和\card"不是正交的,因为它们的第3个字母相同。
给出一个字符串S,求S的字典序最小的正交变形词。如果这样的字符串不存在,就让答案是空串。
字符串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,所有字符都是小写拉丁字母。
另有10%数据,恰有2种不同的字母。
另有20%数据,只有不超过5种不同的字母。
对于80%数据,字符串长度不超过50。
对于100%数据,字符串长度不超过50000,所有字符都是小写拉丁字母。
题解
- 我们可以预处理出每个字母出现的次数l[i]和没有出现的次数r[i]
- 若一个字母出现的次数>没有出现的次数,那么显然这个是没有方案的,因为要满足每一位的字母都不一样,这样的话,就超过n/2个了,显然不能形成
- 现在来想一下如何用预处理出来的数组来求答案
- 考虑贪心的思想,要使字典序最小,那么可以放的最小的字母可以先放
- 那么就枚举放的字母,若l[i]=r[i],也就是说,它占整个字符串的一半,而且我们是按顺序枚举过来的,显然可以放
- 若没有以上的情况,那么我们就找第一个不等于字符串相对位置,而且是出现过的字母放就好了
代码
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 int l[26],r[26],n; 5 char s[50010]; 6 int main() 7 { 8 scanf("%s",s+1),n=strlen(s+1); 9 for (int i=1;i<=n;i++) for (int j=0;j<26;j++) if (s[i]==j+97) l[j]++; else r[j]++; 10 for (int i=0;i<26;i++) if (l[i]>r[i]) return 0; 11 for (int i=1;i<=n;i++) 12 { 13 int x=26; 14 for (int j=0;j<26;j++) if (s[i]!=(j+97)&&l[j]==r[j]) x=j; 15 if (x==26) for (int j=0;j<26;j++) if (s[i]!=(j+97)&&l[j]) {x=j; break;} 16 printf("%c",x+97),l[x]--; 17 for (int j=0;j<26;j++) if (s[i]!=(j+97)) --r[j]; 18 } 19 }