Uva--10069(动规,LCS)

2014-08-02 19:31:50

2014-08-02 16:29:05

Problem E

Distinct Subsequences

Input: standard input<style='mso-bidi-font-weight:normal'>

Output: standard output

 

A subsequence of a given sequence is just the given sequence with some elements (possibly none) left out. Formally, given a sequence X=x1x2xm, another sequence Z=z1z2zk is a subsequence of X if there exists a strictly increasing sequence <i1i2, , ik> of indices of X such that for allj = 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 >.

In this problem 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 10100 distinct occurrences in X 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

思路:这道DP + 高精度,坑我到3点 TAT(还让不让人睡了!),不得不说一下,首先看了下题目,结果比较大(10^100级),果断贴了以前敲的大数模板,竟然RE!无奈把数组改成vector才过,QAQ!

DP的方式有两种:(1)以string 1为基准(也就是放在第一层循环里),扫string 2 ,这种方法比较常见,dp[i][j] 表示子串前 j 个组成的字符串在母船前 i 个组成字符串中的出现次数。

          DP方程:(1) s1[i] == s2[j] : dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j] ;

               (2) s1[i] != s2[j] : dp[i][j] = dp[i - 1][j];

        (2)以string 2 为基准(也就是放在第一层循环里),扫string 1,我是用这种方式来实现的,有些奇葩,但是方程是我自己推的。

          DP方程:

          if(s1[i - 1] == s2[j - 1]){
                     if(j - 1 > 0 && s2[j - 1] == s2[j - 2])
                         dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
                     else
                         dp[i][j] = dp[i][j - 1] + dp[i - 1][j];
                 }
          else
              dp[i][j] = dp[i - 1][j];
  1 /*************************************************************************
  2     > File Name: i.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com
  5     > Created Time: Thu 31 Jul 2014 12:34:01 AM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <iostream>
 14 #include <algorithm>
 15 using namespace std;
 16 #define ll long long
 17 const int maxn = 1000;
 18 
 19 struct bign{
 20     int len;
 21     vector<int> s;
 22 
 23     //初始化与赋值
 24     bign(){
 25         s.clear();
 26         len = 0;//因为0的存在
 27     }
 28 
 29     bign operator = (const char *num){
 30         len = strlen(num);
 31         for(int i = 0; i < len; ++i)
 32             s.push_back(num[len - i - 1] - '0');
 33             //s[i] = num[len - i - 1] - '0';//倒序转化成数字
 34         return *this;
 35     }
 36 
 37     bign operator = (int num){
 38         char ts[maxn + 5];
 39         sprintf(ts,"%d",num);
 40         *this = ts;
 41         return *this;
 42     }
 43 
 44     bign(int num){
 45         *this = num;
 46     }
 47 
 48     //bign的str型转化
 49     string str() const{
 50         string res = "";
 51         for(int i = len - 1; i >= 0; --i)
 52             res +=  (char)(s[i] + '0');
 53         if(res == "")
 54             res = "0";
 55         return res;
 56     }
 57     //运算符重载
 58     //高精度加
 59     bign operator + (const bign & b) const{
 60         bign sum;
 61         sum.len = 0;
 62         for(int i = 0, g = 0; g || i < max(len,b.len); ++i){
 63             int x = g;//x:暂存和,g:进位
 64             if(i < len) x += s[i];
 65             if(i < b.len) x += b.s[i];
 66             sum.s.push_back(x % 10);
 67             sum.len++;
 68             g = x / 10;
 69         }
 70         return sum;
 71     }
 72 
 73     friend ostream & operator << (ostream & out,const bign & x);
 74 };
 75 
 76 ostream & operator << (ostream & out,const bign & x){
 77     out << x.str();
 78     return out;
 79 }
 80 
 81 bign dp[10005][105];
 82 
 83 int main(){
 84     //freopen("in","r",stdin);
 85     int Case;
 86     int len1,len2;
 87 
 88     char s1[10005];
 89     char s2[105];
 90     scanf("%d",&Case);
 91     getchar();
 92     while(Case--){
 93         gets(s1);
 94         gets(s2);
 95         len1 = strlen(s1);
 96         len2 = strlen(s2);
 97         for(int j = 1; j <= len2; ++j){
 98             for(int i = 1; i <= len1; ++i){
 99                 dp[i][0] = 1;
100                 if(s1[i - 1] == s2[j - 1]){
101                     if(j - 1 > 0 && s2[j - 1] == s2[j - 2])
102                         dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
103                     else
104                         dp[i][j] = dp[i][j - 1] + dp[i - 1][j];
105                 }
106                 else
107                     dp[i][j] = dp[i - 1][j];
108             }
109         }
110         cout << dp[len1][len2] << endl;
111     }
112     return 0;
113 }

 

 

转载于:https://www.cnblogs.com/naturepengchen/articles/3887363.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值