卡了我一天的题我还能说是水题吗。。。。
开始的思路【半递推半搜索】虽然是不成熟的动规,但是我觉得至少还能过。
看了人家比较成熟的思路却没有过。
但最后还是用成熟的动规思路过的。
代码挫在了写大数的地方。少了个等号,,,,
状态:d[i][j]表示子串的前i-1个字符在母串前j-1个位置中出现的次数
状态转移:(sub[i-1]==s[j-1])d[i][j] = d[i][j-1]; (sub[i-1]!=s[j-1]) d[i][j] = d[i][j-1]+d[i-1][j-1];
代码如下:
#include <cstdio>
#include <cstring>
#define M 10005
#define N 105
char s[M], sub[N];
int len, s_len, d[N][M][N], t[N] = {0};
void add(int* a, int* b)
{
for(int i = 0; i < N; i++)
{
a[i]+=b[i];
}
for(int i = 0; i < N; i++)
{
if(a[i]>=10)
{
a[i]-=10;
a[i+1]+=1;
}
}
}
void print_ans()
{
int f = 0;
int *ans = d[s_len][len];
for(int i = N-1; i >= 0; i--) {if(ans[i]) f = 1; if(f)printf("%d",ans[i]); }
printf("\n");
}
int main ()
{
int cas;
t[0] = 1;
scanf("%d",&cas);getchar();
while(cas--)
{
gets(s);gets(sub);
len = strlen(s);
s_len = strlen(sub);
memset(d[1][0],0,sizeof(d[1][0]));
for(int i = 1; i <= len; i++)
{
memcpy(d[1][i],d[1][i-1],sizeof(d[i][i-1]));
if(sub[0]==s[i-1]) add(d[1][i],t);
}
for(int i = 2; i <= s_len; i++)
{
for(int j = i; j <= len; j++)
{
memcpy(d[i][j],d[i][j-1],sizeof(d[i][j-1]));
if(s[j-1]==sub[i-1]) add(d[i][j],d[i-1][j-1]);
}
}
print_ans();
}
return 0;
}