• AGC054 A


    传送门

    题意

    给定一个长度为n的字符串s, 每次可以消除i,j之间的字符当第i个字符与第j个不相同时
    求最小消除整个字符串的最小次数。


    题解

    dp解法(考场

    dp还是很简单的。

    考虑朴素的dp, 设(f_{i}) 表示消除前i个字符的最小花费。
    容易想到

    [fi = min_{1leq j < i} {f_{j-1} + 1} \,\,: (S_i eq S_j) ]

    如果我们用一个变量维护到i为止的最小的(f_{j-1})就可以(O(1))转移,但不能满足i, j的字符不同。

    换一个思路, 我们用一个大小为26的数组维护,(d_i)表示最小的(f_{j-1})使得Sj 为 i
    简单的说, 就是维护以某一字符结尾的最小花费
    转移的时候只要这个字符不等于(Si)即可

    不懂可以看看代码?
    总复杂度(O(26n))
    没完呢, 下面还有另一种做法

    const int N = 100005;
    const int inf = 0x3f3f3f3f;
    int n;
    int s[27];
    int a[N];
    
    
    int main(){
      n = read();
      for(int i=1; i<=n; i++){
      	a[i] = readc();
      }
      a[n+1] = 26;
      
      
      for(int i=0; i<=26; i++){
      	s[i] = inf;
      }s[a[1]] = 0;
      
      for(int i=1; i<=n; i++){
      	int res = inf;
      	for(int j=0; j<26; j++){
      		if(a[i] == j) continue;
      		res = min(res, s[j]);
      	}
      	s[a[i+1]] = min(s[a[i+1]], res+1);
      }
      printf("%d
    ", s[26]>=inf?-1:s[26]);
       
      return 0;
    }
    

    贪心解法(题解做法

    我只能说真的妙, 这才能叫AGC把!!

    先说结论: 花费只可能是1,2, 否则不可能消除。(这里给出我的证明

    先说1吧, 假如字符串的首尾不相同, 显然可以一次消掉。

    然后再看2, 假如首尾相同且都是a,显然不能一次消掉。我们考虑如果字符串中存在两个相邻的字符,这两个字符都不等于a,那么这个字符串可以两次消掉。

    否则的话字符串中只存在一个连续的不是a,例如aba, 那么无论我们如何消除,最后都会剩下一个首尾都是a的字符串,无论如何都不能消除。

    妙啊!

  • 相关阅读:
    IOC Unity的配置问题
    编译时常量与运行时常量
    Revit二次开发,将插件按钮(Ribbon)变灰或者隐藏
    C#类库读取App.config配置文件
    winform固定窗体大小
    Revit二次开发,获取模型版本信息
    JavaScript:文件保存自動下載函數:Save和SaveAs
    JavaScript:年月日時分秒設置
    JavaScript:字符串の空格刪減和字符刪減功能
    JavaScript:獲取數據の類型
  • 原文地址:https://www.cnblogs.com/ltdjcoder/p/14968674.html
Copyright © 2020-2023  润新知