1012(hdu 6078) Wavel Sequence
题意:
给出两个序列,找出所有公共子序列,并使得该公共子序列呈波浪状,即
a1<a2>a3<a4>a5<a6...
分析:
很显然是个dp的题,类似最长公共子序列的感觉。
定义fi,j,k 定为以a[i],b[j]结尾的子序列,且峰谷状态为k,k=0表示谷态,k=1表示峰态。
fi,j,k=Σf1~i-1,1~j-1,1-k
定义
gi,j,k=Σf1~i-1,j,k hi,j,k=Σgi,1~j-1,k
那么fi,j,k= hi,j,1-k
时间复杂度从O(n^4)降为O(n^2)
代码:
const int maxn=2e3+10;
const int mod=998244353;
int a[maxn], b[maxn];
int f[maxn][2], g[maxn][2];
int main(){
int cas=0;
int T;
int n, m;
//freopen("input.txt", "r", stdin);
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
for(int i=1;i<=n;i++) scanf("%d", a+i);
for(int j=1;j<=m;j++) scanf("%d", b+j);
int ans=0;
memset(g, 0, sizeof g);
for(int i=1;i<=n;i++){
int h0=0, h1=1;//因为第1位为谷态,所以峰态结尾的个数初始值默认为1
for(int j=1;j<=m;j++)
if(a[i]==b[j]){//相同则进行转移
f[j][0]=h1;//f(i,j,k)= h(i,j,1-k)
f[j][1]=h0;
ans=(ans+(f[j][0]+f[j][1])%mod)%mod;//答案计入总和
}else if(a[i]>b[j]){//a[i]>b[j],则可以从f[i-1][j][0]转移到f[i][j+1][1]
h0=(h0+g[j][0])%mod;
}else{
h1=(h1+g[j][1])%mod;
}
for(int j=1;j<=m;j++)
if(a[i]==b[j]){//更新g, g(i,j,k)=Σf(1~i-1,j,k)
g[j][0]=(g[j][0]+f[j][0])%mod;
g[j][1]=(g[j][1]+f[j][1])%mod;
}
}
printf("%d\n", ans);
}
return 0;
}