zoukankan      html  css  js  c++  java
  • 使字符串有序的最少操作次数

    题意

    给你一个字符串 s (下标从 0 开始)。你需要对 s 执行以下操作直到它变为一个有序字符串:
    找到 最大下标 i ,使得 1 <= i < s.length 且 s[i] < s[i - 1] 。
    找到 最大下标 j ,使得 i <= j < s.length 且对于所有在闭区间 [i, j] 之间的 k 都有 s[k] < s[i - 1] 。
    交换下标为 i - 1​​​​ 和 j​​​​ 处的两个字符。
    将下标 i 开始的字符串后缀反转。
    请你返回将字符串变成有序的最少操作次数。由于答案可能会很大,请返回它对 109 + 7 取余 的结果。

    解析

    实质上是求一个全排列,使其最终有序。例如cba->cab->bca->bac->acb->abc
    本质上是组合计数。确定具有相同前缀,比当前字符小的排列数目。如cba以cb为前缀的只有cba,以c为前缀比b小的前缀只有a,a后面的位置求组合数是C(1,1)。
    设字符串p,那么p后的可能方案满足字符s<p,每个s后的组合数为C(z_a,a1)C(z_a-a1,a2)()...()
    代码如下:

    #define ll long long
    class Solution {
    public:
    //求全排列
        const int mod=1e9+7;
        int c[3050][3050],cnt[26];
        void init(int n)
        {   
            c[0][0]=1;
            for(int i=1;i<=n;i++){
                c[i][0]=c[i][i]=1;
                for(int j=1;j<i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
            }
        }
        ll find(int n,int m)
        {
            if(n==0) return 1ll;
            if(m==0) return 1ll;
            if(m>n)  return 1ll;
            return c[n][m];
        }
        int makeStringSorted(string s) {
            int n=s.size();
            init(n);
            ll ans=0;
            for(int i=n-1;i>=0;i--){
                int val=s[i]-'a';
                cnt[val]++;
                for(int c=val-1;c>=0;c--){ //当前位填c,c<val 在剩余的字母中寻找填入
                    if(cnt[c]==0) continue;
                    cnt[c]-=1;
                    int left=n-i-1;
                    ll cur=1;
                    for(int j=0;j<26;j++){ //剩余的位置填入a-z的字母
                        cur=cur*find(left,cnt[j])%mod;
                        left-=cnt[j];
                    }
                    cnt[c]+=1;
                    ans=(ans+cur)%mod;
                }
            }
            return ans;
        }
    };
    
  • 相关阅读:
    POJ 2236 Wireless Network(并查集)
    POJ 2010 Moo University
    POJ 3614 Sunscreen(贪心,区间单点匹配)
    POJ 2184 Cow Exhibition(背包)
    POJ 1631 Bridging signals(LIS的等价表述)
    POJ 3181 Dollar Dayz(递推,两个long long)
    POJ 3046 Ant Counting(递推,和号优化)
    POJ 3280 Cheapest Palindrome(区间dp)
    POJ 3616 Milking Time(dp)
    POJ 2385 Apple Catching(01背包)
  • 原文地址:https://www.cnblogs.com/flightless/p/14715736.html
Copyright © 2011-2022 走看看