题目:求出两个串S,T,求S中字串T的个数。
分析:dp。状态:f(i,j)为S【0..j-1】中的子串T【0..i-1】的个数。则有状态方程:
f(i,j)= f(i-1,j-1)+ f(i,j-1) {如果,当前S【j-1】的字符和T【i-1】的字符相同}
f(i,j)= f(i,j-1) {如果,当前S【j-1】的字符和T【i-1】的字符不同}
每次发现S【j-1】和T【i-1】匹配,增加子串个数即可。这时增加前缀{f(i-1,j-1)}的个数。
注意:大整数计数。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
char S[10005];
char T[105];
int F[105][10005][30];
int main()
{
int n;
while ( scanf("%d",&n) != EOF )
while ( n -- ) {
scanf("%s%s",S,T);
int ls = strlen(S);
int lt = strlen(T);
memset( F, 0, sizeof(F) );
for ( int j = 1 ; j <= ls ; ++ j ) {
if ( T[0] == S[j-1] )
F[1][j][0] = F[1][j-1][0] + 1;
else F[1][j][0] = F[1][j-1][0];
if ( F[1][j][0] >= 10000 ) {
F[1][j][1] += F[1][j][0]/10000;
F[1][j][0] %= 10000;
}
}
for ( int i = 2 ; i <= lt ; ++ i )
for ( int j = 1 ; j <= ls ; ++ j )
if ( S[j-1] == T[i-1] ) {
for ( int k = 0 ; k <= 24 ; ++ k )
F[i][j][k] = F[i][j-1][k] + F[i-1][j-1][k];
for ( int k = 0 ; k <= 24 ; ++ k )
if ( F[i][j][k] >= 10000 ) {
F[i][j][k+1] += F[i][j][k]/10000;
F[i][j][k+0] %= 10000;
}
}else {
for ( int k = 0 ; k <= 24 ; ++ k )
F[i][j][k] = F[i][j-1][k];
}
int end = 25;
while ( end > 0 && !F[lt][ls][end] ) end --;
printf("%d",F[lt][ls][end --]);
while ( end >= 0 ) printf("%0.4d",F[lt][ls][end --]);
printf("\n");
}
return 0;
}