题目大意:
给定一个长度为n的只含有a,b,c的字符串,对该字符串进行多次(或0次)以下操作:将某个位置的字符变为其左边的或右边的。求操作后所得字符串满足3种字符两两数量差不超过1的有多少个?
n<=150
题目解法:
观察原始字符串A和变化字符串B的关系。
可以发现(赫赫 窝就无法发现)若我们将A和B均进行去重操作分别得到A‘ B‘,那么B‘一定是A‘的子串。它的正确性也是比较显然的(emm某个字符若想跑到前面的字符前面那么一定会将前面的字符覆盖(((
那么我们就可以将原串直接去重得到S,然后我们只需要一位一位生成新串与原串匹配即可。f[i][a][b][c]表示匹配到原串的第i位,有a个‘a‘,b个‘b‘,c个‘c‘的字符串个数,根据下一位字符的三种选择,它可以向后转移到f[nxt[i][‘a‘]][a+1][b][c], f[nxt[i][‘b‘][a][b+1][c], f[nxt[i][‘c‘][a][b][c+1]。其中nxt数组时需要预处理,表示第i位后第一个a/b/c的位置。因为ab和abbb去重后相同显然是可以匹配到相同位置的,因此这里的nxt定义中的下一个包含其本身。
答案统计只需要在计算过程中将满足a+b+c==n且差值不大于1的f值累加起来即可。看似是O(n^4)的复杂度,实际上后面三维大概在n/3的大小(不然某一个字符过多显然无法满足差值上的要求),所以可以在150*50^3内完成,时间复杂度不成问题。
原文:https://www.cnblogs.com/myrcella/p/11761820.html