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 <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
char dp[101][10001][102], str1[10002], str2[102];
void Add(char *c, char *a, char *b)
{
int len_a = strlen(a);
int len_b = strlen(b);
int len_c = max(len_a, len_b);
memset(c, 0, (len_c+2)*sizeof(c[0]));
for(int i=len_a-1, j=len_c; i>=0; --i, --j)
c[j] += a[i] - '0';
for(int i=len_b-1, j=len_c; i>=0; --i, --j)
c[j] += b[i] - '0';
for(int i=len_c; i>0; c[i]+='0', --i)
if(c[i] > 9)
{
c[i] -= 10;
++c[i-1];
}
if(!c[0])
{
for(int i=0; i<len_c; ++i)
c[i] = c[i+1];
c[len_c] = 0;
}
else
c[0] = '1';
}
int main()
{
#ifdef test
freopen("input.txt", "r", stdin);
#endif
int num;
scanf("%d", &num);
while(num--)
{
scanf("%s%s", str1, str2);
int len1 = strlen(str1), len2 = strlen(str2);
for(int i=0; i<=len1; ++i)
strcpy(dp[0][i], "1");
for(int i=1; i<=len2; ++i)
{
strcpy(dp[i][i-1], "0"); // 此语句可有可无,因为dp[i][i-1]本身为‘\0’,不影响加的过程
for(int j=i; j<=len1; ++j)
{
if(str1[j-1] == str2[i-1])
Add(dp[i][j], dp[i][j-1], dp[i-1][j-1]); //dp[i][j] = dp[i][j-1] + dp[i-1][j-1];
else
strcpy(dp[i][j], dp[i][j-1]); //dp[i][j] = dp[i][j-1];
}
}
printf("%s\n", dp[len2][len1]);
}
return 0;
}