Luogu P1944 最长括号匹配
Luogu P1944 最长括号匹配
显然是一道 DP。
设 $f_i$ 为以第 $i$ 位结尾的最长括号匹配子串的长度。
则当 s[i-f[i-1]-1]
与 s[i]
匹配时,$f_i=f_{i-1}+2+f_{i-f_{i-1}-2}$。$f_{i-f_{i-1}-2}$ 表示这个匹配之前可能存在的一个匹配的长度。
特别注意的是,不要在 for
循环里写 strlen(s)
,这样每次循环的时候都要计算一次,会有三个点超时。
代码实现如下:
#include<bits/stdc++.h>
#define N 1000010
int ans,pos;
int f[N];
char s[N];
namespace WalkerV {
void Read() {
scanf("%s",s);
return;
}
void Solve() {
int len=strlen(s);
for(int i=0;i<len;i++) {
if(s[i]==')') {
if(s[i-f[i-1]-1]=='(') {
f[i]=f[i-1]+2+f[i-f[i-1]-2];
}
}
if(s[i]==']') {
if(s[i-f[i-1]-1]=='[') {
f[i]=f[i-1]+2+f[i-f[i-1]-2];
}
}
if(ans<f[i]) {
ans=f[i];
pos=i;
}
//printf("f[%d]:%d\n",i,f[i]);
}
return;
}
void Print() {
//printf("%d %d\n",ans,pos);
for(int i=pos-ans+1;i<=pos;i++) {
printf("%c",s[i]);
}
printf("\n");
return;
}
}
int main()
{
WalkerV::Read();
WalkerV::Solve();
WalkerV::Print();
return 0;
}