题意:在一个母串X中找出字串Z出现的最大次数。
解法:很明显的DP;状态表示:用a[i][j]表示字串的前i个在母串的前j个中出现得最大次数;转移方程:始终有a[i][j] = a[i][j-1],因为字串前i个在母串前j-1个中出现的次数显然也会在母串前j个出现,当x[j]==z[i]时,还要加上字串前i-1个在母串前j-1个出现的次数。可以转化为一维的,具体见代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define Base 1000000000
#define Cap 30
typedef long long hugeint;
struct bignum
{
int Len;
int Data[Cap];
bignum() : Len(0){}
bignum(const bignum &V) : Len(V.Len)
{
memcpy(Data,V.Data,Len * sizeof*Data);
}
bignum(int V) : Len(0)
{
for(;V > 0;V /= Base)
Data[Len++] = V % Base;
}
bignum &operator = (const bignum &V)
{
Len = V.Len;
memcpy(Data,V.Data,Len * sizeof*Data);
return *this;
}
int &operator[](int Index)
{
return Data[Index];
}
int operator[](int Index) const
{
return Data[Index];
}
};
bignum operator+(const bignum &A, const bignum &B)
{
bignum R;
int i;
int Carry = 0;
for(i = 0; i < A.Len || i < B.Len || Carry > 0; i++)
{
if(i < A.Len)
Carry += A[i];
if(i < B.Len)
Carry += B[i];
R[i] = Carry % Base;
Carry /= Base;
}
R.Len = i;
return R;
}
ostream& operator<<(ostream &Out, const bignum &V)
{
int i;
Out << (V.Len == 0 ? 0 : V[V.Len - 1]);
for(i = V.Len - 2; i >= 0; i--)
for(int J = Base / 10; J > 0; J /= 10)
Out << V[i] / J % 10;
return Out;
}
#define M 105
#define N 10005
bignum d[M];
char s1[N], s2[M];
int main()
{
int t, l1, l2;
scanf("%d", &t);
while(t--)
{
scanf("%s %s", &s1, &s2);
l1 = strlen(s1), l2 = strlen(s2);
for(int i = 1; i <= l2; i++) d[i] = bignum(0);
d[0] = bignum(1);
for(int i = 1; i <= l1; i++)
for(int j = l2; j >= max(l2 - l1 + i, 1); j--)
{
if(s1[i - 1] == s2[j - 1])
{
d[j] = d[j] + d[j - 1];
}
}
cout <<d[l2]<<endl;
}
return 0;
}