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=x1x2 xm, another sequence Z=z1z2 zk is a subsequence of X if there exists a strictly increasing sequence <i1, i2, , 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 }