百度 2021.04.11 笔试 字符串S转化为T的方案

在这里插入图片描述
参考牛客大佬:大佬1 大佬2

思路——动态规划

  • 记字符串长度为 n n n
  • 首先将字符串 S = x y S=xy S=xy变换为 y x yx yx,等价于将字符串 S S S循环右移或左移(读者可以自己举例子尝试一下)
  • 那么,只要 T T T S S S的循环同构串,当 S ! = T S != T S!=T时, S S S只要经过 1 1 1次操作即可变换为 T T T;当 S = = T S == T S==T时, S S S经过 0 0 0次操作即可变换为 T T T
  • 现在,称字符串循环左移 ( j + n ) % n (j+n)\%n (j+n)%n个位置得到的新字符串称为字符串 j j j
  • 定义 d p [ i ] [ j ] dp[i][j] dp[i][j]为字符串S经过 i i i次操作后,得到字符串 j j j的操作方案。其中, 0 ≤ i ≤ k , 0 ≤ j ≤ n − 1 0 \le i \le k, 0 \le j \le n-1 0ik,0jn1
  • 显然字符串 s s s经过 1 1 1次操作可以变换到任意字符串 x x x,除非 s = = x s==x s==x。同样地,任意字符串 x x x也可以经过一次操作变换到字符串 j j j,除非 j = = x j==x j==x
  • 那么有
    d p [ i ] [ j ] = s u m ( d p [ i − 1 ] [ x ] ) , 0 ≤ x ≤ n − 1   a n d    x ≠ j dp[i][j]=sum(dp[i-1][x]), 0 \le x \le n-1 \, and \; x \neq j dp[i][j]=sum(dp[i1][x]),0xn1andx=j
  • 然后空间压缩即可。否则 n ∗ k n*k nk的数据会爆内存
  • 时间复杂度 O ( n k ) O(nk) O(nk) ,空间复杂度 O ( n ) O(n) O(n)

压缩 i i i这个维度的代码:

#include "bits/stdc++.h"
using namespace std;
constexpr int MOD = 1e9 + 7;
using LL = long long;
string S, T;
int k;
LL d[2][1005];
LL sum[2];
int n;
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	while (cin >> S >> T >> k) {
		memset(d, 0, sizeof d);
		memset(sum, 0, sizeof sum);
		n = S.size();
		d[0][0] = 1;
		sum[0] = 1;
		for (int i = 1; i <= k; ++i) {
			sum[i & 1] = 0;
			for (int j = 0; j < n; ++j) {
				d[i & 1][j] = (sum[(i + 1) & 1] + MOD - d[(i + 1) & 1][j]) % MOD;
				sum[i & 1] = (sum[i & 1] + d[i & 1][j]) % MOD;
			}
		}
		LL ans = 0;
		for (int i = 0; i < n; ++i) {
			string tmp = S.substr(i) + S.substr(0, i);
			if (tmp == T) {
				ans = (ans + d[k & 1][i]) % MOD;
			}
		}
		cout << ans << endl;
	}

}
/*
aaca
caaa
2

ac
ca
2
*/

另一种思路

  • 首先计算出 S S S经过1次变换或0次变换到达 T T T的操作方案个数。那么这也是任意一个字符串变换为T的方案个数。记该操作方案个数为 c n t cnt cnt。注意cnt中可能包含自身变换到自身的情况。
  • 定义 d p [ i ] [ 0 ] dp[i][0] dp[i][0]为经过 i i i次操作之后,无法到达 T T T的个数。 d p [ i ] [ 1 ] dp[i][1] dp[i][1]为经过 i i i次操作之后,到达 T T T的个数
  • 那么有
    d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] × ( n − c n t − 1 ) + d p [ i − 1 ] [ 1 ] × ( n − c n t ) d p [ i ] [ 1 ] = d p [ i − 1 ] [ 0 ] × c n t + d p [ i − 1 ] [ 1 ] × ( c n t − 1 ) dp[i][0]=dp[i-1][0] \times (n-cnt-1)+dp[i-1][1] \times (n-cnt) \\ dp[i][1]=dp[i-1][0] \times cnt + dp[i-1][1] \times (cnt-1) dp[i][0]=dp[i1][0]×(ncnt1)+dp[i1][1]×(ncnt)dp[i][1]=dp[i1][0]×cnt+dp[i1][1]×(cnt1)
  • 时间复杂度 O ( k ) O(k) O(k) ,空间复杂度 O ( k ) O(k) O(k)
  • 同样可以对第一维的空间压缩,那么空间复杂度将会是 O ( 1 ) O(1) O(1)
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值