【TCO 2012】WildCard SemiMultiple 区间DP

很好的区间DP题目。

Description

给出两个串A,B。每次可以往A中插入一个字符。
将每次操作后的A串记为一个序列。
求从A串变为B串的不同序列数量。

Difficulty

★★★★

Main Algorithm

DP

Complexity

Solution

不妨先考虑一个简单的情况,即A为空串。
即每次插入一个字符,得到B串,这样的序列数量的统计。
考虑如何去重。什么情况下会有重复串呢?只有在B串出现了连续相同字符的时候,这时候插入这些字符的先后顺序是没有影响的。
为了去掉这一点的影响,不妨规定往连续相同字符中插入时只能插入到这一段的开头。
设   表示得到   这一段的方案数。如何在转移时将上述规定表述出来?
不妨设第一个插入的字符是   ,那么 
故转移就可得了: .
接下来考虑怎么处理A不为空。试图将B拆成很多段,有的段与A中的一部分匹配,别的我们就可以视作是从空->有的利用上述算法得到。
设   表示A串匹配到了i,B串匹配到了j的方案数。
枚举   匹配到了   ,需要满足  .
.
这样,问题就成功解决了。

----------------------- 转自 picks

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define Rep(i, x, y) for (int i = x; i <= y; i ++)
#define Dwn(i, x, y) for (int i = x; i >= y; i --)
#define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex)
using namespace std;
typedef long long LL;
const int mod = 1000000007, N = 205;
class StringSequences {
public:
	int s1[N], s2[N], n, m;
	LL f[N][N], g[N][N], ans, C[N][N];
	int countSequences(string A, string B) {
		n = A.size(), m = B.size();
		cout << n << endl;
		Rep(i, 1, n) s1[i] = A[i - 1];
		Rep(i, 1, m) s2[i] = B[i - 1];
		Rep(i, 1, m + 1) f[i][i] = 1;
		C[0][0] = 1;
		Rep(i, 1, m) {
			C[i][0] = 1;
			Rep(j, 1, i) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
		}
		Rep(l, 1, m) {
			Rep(i, 1, m - l + 1) {
				int j = i + l;
				Rep(k, i, j - 1) if (s2[k] != s2[j]) (f[i][j] += (f[i][k] * f[k + 1][j] % mod) * C[j - i - 1][k - i]) %= mod;
			}
		}
		g[0][0] = 1;
		Rep(i, 1, n) {
			Rep(j, 1, m) if (s1[i] == s2[j]) {
				Rep(k, 0, j - 1) {
					(g[i][j] += (g[i - 1][k] * f[k + 1][j] % mod) * C[m - n - k + i - 1][j - k - 1]) %= mod;
				}
			}
		}
		Rep(j, 1, m) (ans += g[n][j] * f[j + 1][m + 1]) %= mod;
		return (int)ans;
	}
};



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值