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 |
Description
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=x1x2…xm, another sequenceZ=z1z2…zk
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