// Distinct Subsequences (不同的子序列)
// PC/UVa IDs: 111102/10069, Popularity: B, Success rate: average Level: 3
// Verdict: Accepted
// Submission Date: 2011-10-10
// UVa Run Time: 0.026s
//
// 版权所有(C)2011,邱秋。metaphysis # yeah dot net
//
// [Problem Description]
// A subsequence of a given sequence S consists of S with zero or more elements
// deleted. Formally, a sequence Z = z1 z2 . . . zk is a subsequence of X = x1
// x2 . . . xm if there exists a strictly increasing sequence < i1 , i2 , . . . ,
// ik > of indices of X such that for all j = 1, 2, . . . , k, we have xij = zj.
// For example, Z = bcdb is a subsequence of X = abcbdab with corresponding index
// sequence < 2, 3, 5, 7 >.
//
// Your job is to write a program that counts the number of occurrences of Z in
// X as a subsequence such that each has a distinct index sequence.
//
// [Input]
// The first line of the input contains an integer N indicating the number of test
// cases to follow. The first line of each test case contains a string X, composed
// entirely of lowercase alphabetic characters and having length no greater than
// 10,000. The second line contains another string Z having length no greater than
// 100 and also composed of only lowercase alphabetic characters. Be assured that
// neither Z nor any prefix or suffix of Z will have more than 10^100 distinct
// occurrences in X as a subsequence.
//
// [Output]
// For each test case, output the number of distinct occurrences of Z in X as a
// subsequence. Output for each input set must be on a separate line.
//
// [Sample Input]
// 2
// babgbag
// bag
// rabbbit
// rabbit
//
// [Sample Output]
// 5
// 3
//
// [解题方法]
// 此题需要使用大数运算。使用一点 DP 即可。关键是如何得到递推关系,可以这样想,设母串的长度为 j,
// 子串的长度为 i,我们要求的就是长度为 i 的字串在长度为 j 的母串中出现的次数,设为 t[i][j],若
// 母串的最后一个字符与子串的最后一个字符不同,则长度为 i 的子串在长度为 j 的母串中出现的次数就是
// 母串的前 j - 1 个字符中子串出现的次数,即 t[i][j] = t[i][j - 1],若母串的最后一个字符与子
// 串的最后一个字符相同,那么除了前 j - 1 个字符出现字串的次数外,还要加上子串的前 i - 1 个字符
// 在母串的前 j - 1 个字符中出现的次数,即 t[i][j] = t[i][j - 1] + t[i - 1][j - 1]。
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;
#define MAXZ 101
class integer
{
friend ostream& operator<<(ostream&, const integer&);
public:
integer() { };
// 将无符号整数转换为大整数。
integer(unsigned int orginal)
{
do
{
digits.push_back(orginal % base);
orginal /= base;
} while (orginal);
};
~integer() { };
integer operator+(const integer&);
integer& operator+=(const integer&);
private:
vector < unsigned int > digits; // 数位。
static unsigned int const base = 10000; // 基数。
static unsigned int const width = 4; // 数位宽度。
};
// 重载输出符号 <<。
ostream& operator<<(ostream& os, const integer &number)
{
os << number.digits[number.digits.size() - 1];
for (int i = number.digits.size() - 2; i >= 0; i--)
os << setw(number.width) << setfill('0') << number.digits[i];
return os;
}
integer& integer::operator+=(const integer &b)
{
return *this = *this + b;
}
// 加法。
integer integer::operator+(const integer &b)
{
integer c;
int carry = 0;
for (int i = 0; i < digits.size() || i < b.digits.size() || carry; i++)
{
if (i < digits.size())
carry += digits[i];
if (i < b.digits.size())
carry += b.digits[i];
c.digits.push_back(carry % base);
carry /= base;
}
return c;
}
void distinctSubsequences(string x, string z)
{
// 若为二维数组,可能因数据量多而会溢出导致段错误,故使用滚动数组来计算节省空间。
// 当计算 t[i][j] 时,数组中保存的是 t[i][j - 1] 和 t[i - 1][j - 1] 的数据。
integer occurrences[MAXZ];
int xLength = x.length();
int zLength = z.length();
// 为 DP 准备初始条件。长度为 0 的子串在长度为 0 的母串中出现次数为 1,长度不为 0 的
// 子串在长度为 0 的母串中出现次数为 0。
occurrences[0] = integer(1);
for (int i = 1; i <= zLength; i++)
occurrences[i] = integer(0);
// DP 求出现次数。
for (int i = 1; i <= xLength; i++)
for (int j = zLength; j >= max(int(zLength - xLength + i), 1); j--)
if (x[i - 1] == z[j - 1])
occurrences[j] += occurrences[j - 1];
cout << occurrences[z.length()] << endl;
}
int main(int ac, char *av[])
{
string x, z;
int cases;
cin >> cases;
while (cases--)
{
cin >> x >> z;
if (x.length() < z.length())
cout << 0 << endl;
else
distinctSubsequences(x, z);
}
return 0;
}
UVa Problem 10069 Distinct Subsequences (不同的子序列)
最新推荐文章于 2021-08-04 15:15:41 发布