这题真的长见识了哈哈
https://codeforces.com/contest/1363/problem/F
给字符串s、t,可对s进行局部右旋操作,求将s转变成t的最小操作数。
经过分析我们发现,右旋的本质是将右边的某个字符挪到左边。我们从后往前尝试满足t字符串的匹配。例如首先看s[n]是否等于t[n],如果不相等,将s[n]拿起来准备插入前面的某个位置,注意这时它处于“悬而未决”状态,接下来我们不断前移s的指针i去匹配t的后缀直至全部匹配,每次都尝试三种情况:
直接把s[i]拿起、i–,花费++
如果s[i]=t[j]则直接匹配,双方指针都向前挪动、
如果悬而未决的元素中有能匹配t[j]的,则用它去匹配,然后j–,这个判断需要记录字符的后缀和。
然后我们令dp[i][j]表示从两个指针分别等于i和j时开始到整个匹配过程结束所需的花费,根据前述三种情况,这个dp最适合用递归实现。
1 |
|
还有一种做法好理解,我们设想,如果允许左旋和右旋,那么直接找到两者最长公共子序列长度len,然后n-len就是答案,因为剩余相对关系混乱的元素只需要移动一次就能排好。然鹅现在只支持右旋,所以我们在求最长公共子序列时受到限制,在+1时需要保证s右边字符都大于等于t的右边字符数,因为混乱元素只能向左移不能向右。