给一串由(, ), [ ,]构成的字符串,求包含[最多的合法子串
很容易,先把整个字符串丢入栈里处理
栈的每一个元素存两个东西,字符,在字符串中的位置
处理方式为如果是()匹配则直接丢弃,如果是[]匹配则在这个点vis[i]++,然后求vis的前缀和
如果栈空,则说明整个串是合法的,直接输出串
否则,扫描栈中剩下的元素的位置,这几个位置把整个原串切割成几段,这几段肯定是合法的,求这几段中的含[最大的段,可以用前缀和求得,输出这段
游标,左右区间非常容易弄错。有一次手动输出了'\0',导致看起来和答案一样,就是WA
#include <cstdio>
#include <climits>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
char str[111111];
int vis[111111];
int sumvis[111111];
struct STACK{
char c;
int pos;
}sta[111111];
int main(){
#ifndef ONLINE_JUDGE
freopen("/home/rainto96/in.txt","r",stdin);
#endif
cin>>str;
int p=-1;
int len =strlen(str);
for(int i=0;i<len;i++){
if(p!=-1){
if(str[i]==')' && sta[p].c=='('){//直接丢弃
p--;
continue;
}
if(str[i]==']' && sta[p].c=='[') {//vis[i]++,便于快速求得段中含[的个数
p--;
vis[i]++;
continue;
}
sta[++p]=(STACK){str[i],i};
}else sta[++p]=(STACK){str[i],i};
}
sumvis[0]=vis[0];
for(int i=1;i<len;i++)
sumvis[i]=sumvis[i-1]+vis[i];
if(p==-1){//如果栈里没有东西,则整个字符串合法,输出该串
cout<<sumvis[len-1]<<endl;
cout<<str<<endl;
return 0;
}
int x=-1,y=-1,ans=0;//求栈中剩下元素使得原串分割的段中含[的最多的串
int ansx=-1,ansy=-1;
for(int i=0;i<=p;i++){
y=sta[i].pos;
int tmpans=sumvis[y-1]-sumvis[x]+(x==0?vis[x]:0);
if(tmpans>ans){
ans=tmpans;
ansx=x+1;
ansy=y-1;
}
x=y;
}
y=len;
int tmpans=sumvis[y-1]-sumvis[x]+(x==0?vis[x]:0);
if(tmpans>ans){
ans=tmpans;
ansx=x+1;
ansy=y-1;
}
cout<<ans<<endl;
//cout<<x<<endl;
//cout<<y<<endl;
if(ans>0){
for(int i=ansx;i<=ansy;i++)
cout<<str[i];
}
cout<<endl;
}