题意:长度为n的括号序列,包括'[]','()'.要求找到一个正确的括号区间[L,R]并且'['的数量最多.
n<=1e5.输出最多'['的值和区间[L,R].
因为'['为左端点时,下一个数只能为']'或者左括号.设dp[i]为左端点为i时最远能完成匹配的位置.
若s[i]==']'||s[i]==')] dp[i]=-1;
若s[i]=='[' 当s[i+1]==']' dp[i]=max(i+2,dp[i+2]) ,当s[i+1]=='[||(' p=dp[i+1]+1并且s[p]==']' dp[i]=max(p,dp[p+1])
n<=1e5.输出最多'['的值和区间[L,R].
因为'['为左端点时,下一个数只能为']'或者左括号.设dp[i]为左端点为i时最远能完成匹配的位置.
若s[i]==']'||s[i]==')] dp[i]=-1;
若s[i]=='[' 当s[i+1]==']' dp[i]=max(i+2,dp[i+2]) ,当s[i+1]=='[||(' p=dp[i+1]+1并且s[p]==']' dp[i]=max(p,dp[p+1])
枚举左端点i,右端点R=dp[i].预处理'['的前缀和即可.
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
char s[N];
int L,R=-1,res=0,dp[N],pr[N];
int main()
{
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=1;i<=n;i++)
{
pr[i]=pr[i-1];
if(s[i]=='[')
pr[i]++;
}
for(int i=n;i>=1;i--)
{
if(s[i]==')'||s[i]==']')
{
dp[i]=i-1;
continue;
}
if(s[i]=='('&&s[i+1]==']' || s[i]=='['&&s[i+1]==')')
continue;
if(s[i]=='[')
{
if(s[i+1]==']')
dp[i]=max(i+1,dp[i+2]);
else
{
int p=dp[i+1]+1;
if(s[p]==']')
dp[i]=max(p,dp[p+1]);
else
dp[i]=i-1;
}
}
if(s[i]=='(')
{
if(s[i+1]==')')
dp[i]=max(i+1,dp[i+2]);
else
{
int p=dp[i+1]+1;
if(s[p]==')')
dp[i]=max(p,dp[p+1]);
else
dp[i]=i-1;
}
}
// cout<<i<<' '<<dp[i]<<'\n';
}
for(int i=1;i<=n;i++)
{
int l=i,r=dp[i],cnt=pr[r]-pr[l-1];
if(cnt>res)
{
res=cnt;
L=l,R=r;
}
}
printf("%d\n",res);
for(int i=L;i<=R;i++)
printf("%c",s[i]);
printf("\n");
return 0;
}
標程解法:用棧維護左括號的二元組(s[i],i) 為每個右括號匹配其位置.
模擬時 若棧頂和s[i]不匹配. 出現非法對,則清空棧.
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl "\n"
#define int long long
const int N=1e5+5;
int n;
int pref[N], leftidx[N], bestend[N];
string s;
map<char, char> opp;
stack<pair<char, int> > st;
int range(int l, int r)
{
if(l>=1)
return pref[r] - pref[l-1];
return pref[r];
}
int32_t main()
{
IOS;
cin>>s;
n=s.size();
for(int i=0;i<n;i++)
{
if(i>=1)
pref[i]=pref[i-1] + (s[i]=='[');
else
pref[i]=(s[i]=='[');
}
int ans=0, idx=0, len=0;
opp[')']='(';
opp[']']='[';
for(int i=0;i<n;i++)
{
if(s[i]=='('||s[i]=='[')
{
st.push({s[i], i});
}
else
{
if(!st.size())
continue;
if(st.top().first!=opp[s[i]])
{
while(st.size())
st.pop();
}
else
{
pair<char, int> p=st.top();
st.pop();
int store=0;
if(p.second>=1)
store=bestend[p.second-1];
if(store + range(p.second, i)>ans)
{
ans=store + range(p.second, i);
idx=p.second;
if(store>0)
idx=leftidx[p.second-1];
len=i-idx+1;
}
bestend[i]=store + range(p.second, i);
leftidx[i]=p.second;
if(store>0)
leftidx[i]=leftidx[p.second-1];
}
}
}
cout<<ans<<endl;
cout<<s.substr(idx, len);
return 0;
}