P2679 子串
首先设f[i][j][p]
表示在(A)串中选(i)个字符被划分为(k)段匹配(B)串中的(j)个字符方案数,但是发现还不够,因为当前选还是不选的(k)转移取决于上个字符选没有选没。所以我们再设一维状态(0/1)表示当前字符选或者不选的方案数。
转移:1.如果a[i]==b[j]
,
f[i][j][p][0]=f[i-1][j][p][0]+f[i-1][j][p][1];
这一位不拿,不累加j-1的合法状态
f[i][j][p][1]=f[i-1][j-1][p][0]+f[i-1][j-1][p-1][1]+f[i-1][j-1][p][1];
f[i-1][j-1][p][0] 最后一位不匹配,必须重新划分区间,必须从p中转,不累加p-1的合法状态
f[i-1][j-1][p-1][1] 最后一位匹配,但不重新划分区间,必须从p-1中转,累加p-1的合法状态
f[i-1][j-1][p][1] 最后一位匹配,重新划分一个区间,p不变,直接中转
2.如果a[i]!=b[j]
,
f[i][j][p][0]=f[i-1][j][p][0]+f[i-1][j][p][1];
同上
f[i][j][p][1]=0 因为字符不同无法匹配,所以直接为0
初始化
for (int i=0;i<=n;i++)
f[i][0][0][0]=f[i][0][0][1]=1;
不管i选几个让B串中匹配的数为0的只有一种,就是什么都不选
f[0][0][0][0]和f[0][0][0][1]也要初始化,因为中转要用到
70分
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const int N=510,M=51,mod=1e9+7;
char a[N],b[M];
int f[N][M][M][2];
int n,m,k;
int main()
{
scanf("%d%d%d",&n,&m,&k);
scanf("%s%s",a+1,b+1);
for (int i=0;i<=n;i++)
f[i][0][0][0]=1;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
for (int p=1;p<=k;p++)
if (a[i]==b[j])
{
f[i][j][p][0]=((ll)f[i-1][j][p][0]+f[i-1][j][p][1])%mod;
f[i][j][p][1]=((ll)f[i-1][j-1][p][1]+f[i-1][j-1][p-1][0]+f[i-1][j-1][p-1][1])%mod;
}
else
{
f[i][j][p][0]=((ll)f[i-1][j][p][0]+f[i-1][j][p][1])%mod;
f[i][j][p][1]=0;
}
printf("%d
",(f[n][m][k][1]+f[n][m][k][0])%mod);
return 0;
}
因为数据比较大,直接(DP)会(MLE),但是我们观察发现,每次中转只用到i-1和i,所以我们用滚动数组来代替第一维
初始设now=1,因为1对xor运算无影响
now1就相当于i-1,因为11=0,0^1=1,所以实现了数组的滚动。
最后输出n^1,如果n是单数,肯定滚动到1,偶数滚动到0,所以判断奇偶。
100分
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const int N=1010,M=210,mod=1e9+7;
char a[N],b[M];
int f[2][M][M][2];
int n,m,k;
bool now=1;
int main()
{
scanf("%d%d%d",&n,&m,&k);
scanf("%s%s",a+1,b+1);
f[0][0][0][0]=f[1][0][0][0]=1;
now=1;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
for (int p=1;p<=k;p++)
if (a[i]==b[j])
{
f[now][j][p][0]=((ll)f[now^1][j][p][0]+f[now^1][j][p][1])%mod;
f[now][j][p][1]=((ll)f[now^1][j-1][p][1]+f[now^1][j-1][p-1][0]+f[now^1][j-1][p-1][1])%mod;
}
else
{
f[now][j][p][0]=((ll)f[now^1][j][p][0]+f[now^1][j][p][1])%mod;
f[now][j][p][1]=0;
}
now^=1;
}
printf("%d
",(f[n&1][m][k][1]+f[n&1][m][k][0])%mod);
return 0;
}