UVa 10069 - Distinct Subsequences

dp+大数加法。

设母串的长度为 j, 子串的长度为 i,我们要求的就是长度为 i 的字串在长度为 j 的母串中出现的次数。

(1)若母串的最后一个字符与子串的最后一个字符不同,则长度为 i 的子串在长度为 j 的母串中出现的次数就是母串的前 j - 1 个字符中子串出现的次数,即 str[i][j] = str[i][j - 1];

(2)若母串的最后一个字符与子串的最后一个字符相同,那么除了前 j - 1 个字符出现子串的次数外,还要加上子串的前 i - 1 个字符在母串的前 j - 1 个字符中出现的次数(再加上当前相等的这个字符其长度就可以凑成完整的字串长度),即 str[i][j] = str[i][j - 1] + str[i - 1][j - 1]。

#include<iostream>
#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 200;
struct bign{
  int len, s[maxn];

  bign() {
    memset(s, 0, sizeof(s));
    len = 1;
  }

  bign(int num) {
    *this = num;
  }

  bign(const char* num) {
    *this = num;
  }

  bign operator = (int num) {
    char s[maxn];
    sprintf(s, "%d", num);
    *this = s;
    return *this;
  }

  bign operator = (const char* num) {
    len = strlen(num);
    for(int i = 0; i < len; i++) s[i] = num[len-i-1] - '0';
    return *this;
  }

  string str() const {
    string res = "";
    for(int i = 0; i < len; i++) res = (char)(s[i] + '0') + res;
    if(res == "") res = "0";
    return res;
  }

  bign operator + (const bign& b) const{
    bign c;
    c.len = 0;
    for(int i = 0, g = 0; g || i < max(len, b.len); i++) {
      int x = g;
      if(i < len) x += s[i];
      if(i < b.len) x += b.s[i];
      c.s[c.len++] = x % 10;
      g = x / 10;
    }
    return c;
  }

  void clean() {
    while(len > 1 && !s[len-1]) len--;
  }

  bign operator * (const bign& b) {
    bign c; c.len = len + b.len;
    for(int i = 0; i < len; i++)
      for(int j = 0; j < b.len; j++)
        c.s[i+j] += s[i] * b.s[j];
    for(int i = 0; i < c.len-1; i++){
      c.s[i+1] += c.s[i] / 10;
      c.s[i] %= 10;
    }
    c.clean();
    return c;
  }

  bign operator - (const bign& b) {
    bign c; c.len = 0;
    for(int i = 0, g = 0; i < len; i++) {
      int x = s[i] - g;
      if(i < b.len) x -= b.s[i];
      if(x >= 0) g = 0;
      else {
        g = 1;
        x += 10;
      }
      c.s[c.len++] = x;
    }
    c.clean();
    return c;
  }

  bool operator < (const bign& b) const{
    if(len != b.len) return len < b.len;
    for(int i = len-1; i >= 0; i--)
      if(s[i] != b.s[i]) return s[i] < b.s[i];
    return false;
  }

  bool operator > (const bign& b) const{
    return b < *this;
  }

  bool operator <= (const bign& b) {
    return !(b > *this);
  }

  bool operator == (const bign& b) {
    return !(b < *this) && !(*this < b);
  }

  bign operator += (const bign& b) {
    *this = *this + b;
    return *this;
  }
};

istream& operator >> (istream &in, bign& x) {
  string s;
  in >> s;
  x = s.c_str();
  return in;
}

ostream& operator << (ostream &out, const bign& x) {
  out << x.str();
  return out;
}
bign dp[110][10010];
int main()
{
	int T,i,j,lena,lenb;
	string a,b;
	cin>>T;
	while(T--)
	{
		cin>>a>>b;
		lena=a.length();
		lenb=b.length();
		for(i=1;i<=lenb;i++)
		{
			for(j=i;j<=lena;j++)
				if(a[j-1]!=b[i-1])
					dp[i][j]=dp[i][j-1];
				else
				{
					dp[i][j]=dp[i][j-1]+dp[i-1][j-1];
					if(i==1)//第一个字母相同时,必然要+1 
						dp[i][j]=dp[i][j]+1;
				}
		}
		cout<<dp[lenb][lena]<<endl;
	}
	return 0;
}


Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu

SubmitStatus

Description

Download as PDF

Problem E

Distinct Subsequences

Input: standard input

Output: standard output

 

A subsequence of a given sequence is just the given sequence with some elements (possibly none) left out. Formally, given a sequenceX=x1x2xm, another sequenceZ=z1z2zk is a subsequence ofX if there exists a strictly increasing sequence <i1, i2, …, ik> of indices ofX such that for all j = 1, 2, …, k, we havexij=zj. For example,Z=bcdb is a subsequence of X=abcbdab with corresponding index sequence< 2, 3, 5, 7 >.

In this problem your job is to write a program that counts the number of occurrences ofZ 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 stringZ having length no greater than 100 and also composed of only lowercase alphabetic characters. Be assured that neitherZ nor any prefix or suffix of Z will have more than 10100 distinct occurrences inX as a subsequence.

 

Output

For each test case in the input 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
____________________________________________________________________________________
Rezaul Alam Chowdhury

Source

Root :: AOAPC I: Beginning Algorithm Contests (Rujia Liu) :: Volume 5. Dynamic Programming
Root :: Competitive Programming 3: The New Lower Bound of Programming Contests (Steven & Felix Halim) :: More Advanced Topics :: More Advanced DP Techniques :: DP level 2
Root :: Programming Challenges (Skiena & Revilla) :: Chapter 11
Root :: Prominent Problemsetters :: Rezaul Alam Chowdhury
Root :: Competitive Programming 2: This increases the lower bound of Programming Contests. Again (Steven & Felix Halim) :: More Advanced Topics :: More Advanced Dynamic Programming :: The More Challenging Ones
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值