zoukankan      html  css  js  c++  java
  • [贪心][字符串] Jzoj P3207 Orthogonal Anagram

    Description

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

    字符串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,所有字符都是小写拉丁字母。

    题解

    • 我们可以预处理出每个字母出现的次数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 }
  • 相关阅读:
    cnpm 安装和 command not found
    C#-弄懂泛型和协变、逆变
    2019年阅读
    ES5和ES6数组方法
    ASP.NET MVC中的捆绑和压缩技术
    markdown解析与着色
    Oauth2.0
    同源策略和跨域的解决方案
    windows常用命令
    Java 9 在win10环境搭建
  • 原文地址:https://www.cnblogs.com/Comfortable/p/10331814.html
Copyright © 2011-2022 走看看