// Distinct subsequences (different subsequences) // PC/Ultraviolet IDs: 111102/10069, popularity: B, success rate: average level: 3 // verdict: accepted // submission date: 2011-10-10 // UV Run Time: 0.026 S // copyright (c) 2011, Qiu. 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 su Bsequence 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 /// /[solution] // This question requires the calculation of large numbers. Use a little DP. The key is how to obtain the recursive relationship. You can think like this: Set the length of the parent string to J, and the length of the // sub-string to I, we require that the number of times that a string with the length of I appears in the parent string with the length of J be set to T [I] [J], if // The last character of the parent string is different from the last character of the Child string, then, the number of times that a substring with the length of I appears in the parent string with the length of J is the number of times that the first J-1 character neutron string of the parent string appears, that is, t [I] [J] = T [I] [J-1]. If the last character of the parent string is the same as the last character of the Child // string, in addition to the number of times that the first J-1 character string appears, add the first I-1 character of the substring // the number of times it appears in the first J-1 character of the parent string, that is, 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 () {}; // convert unsigned integers to large integers. 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; // number. Static unsigned int const base = 10000; // base number. Static unsigned int const width = 4; // digital width .}; // Reload the output symbol <. 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;} // addition. 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) {// if it is a two-dimensional array, segment errors may be caused by overflow due to a large amount of data. Therefore, the scrolling array is used to save space. // When T [I] [J] is calculated, the data stored in the array is t [I] [J-1] and T [I-1] [J-1. Integer occurrences [maxz]; int xlength = x. Length (); int zlength = Z. Length (); // prepare the initial conditions for DP. The number of times that a substring with a length of 0 appears in the parent string with a length of 0 is 1, if the length is not 0, the number of occurrences of a substring in the parent string with the length of 0 is 0. Occurrences [0] = INTEGER (1); For (INT I = 1; I <= zlength; I ++) Occurrences [I] = INTEGER (0 ); // DP calculates the number of occurrences. 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; elsedistinctsubsequences (x, z);} return 0 ;}