题意:
给你一个包含'(',')','?'的字符串。然后定义严格前缀,s[1...x] 1<=x<|s|
让你用 '(' 或 ')' 替换 '?',使得s串的严格前缀都不是正确的圆括号,但是s是正确的圆括号
圆括号的定义就是串中所有'('都能正确匹配一个')' '()()' '(())'
解析:
括号匹配的题目是真的做不来...想了一天...
然后想出思路,被之前写的特判卡出了,看了题目的数据才发现错了...
2
??
这个是可以的'()'
思路其实很简单,s[1]=s[2]='('
s[n-1]=s[n]=')'
然后剩下的就只需要把s[2..n-1]的串正确转换成圆括号就可以了。
做法就是先把所有‘?’换成‘(’。
然后扫一遍看多出多少个‘(’,定义x为多的‘(’个数
如果x<0||x&1都是不可能的,
然后x==0直接输出就可以了
剩下我们只需要把多出来的‘(’解决。
解决方法就是把把最靠右边的x/2个‘?’换成‘)’,即从尾扫到头,每遇到一个原来是‘?’的换成‘)’,同时x-=2
最后还需要在扫一遍检查你换的是不是正确的,如果正确的,那么输出,否则的话,就是不可能的。
因为存在这种情况
((???((()) -> (()))((())
因为你多的可能不是由‘?’转换来的‘(’而是本身的‘(’,但是这个‘(’你是不能变的,所以只能是无解
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 3e5+10;
char s[N];
char ans[N];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",s+1);
int flag=0;
int top=0;
if(n<4||(n&1))
{
if(n==2)
{
if(strcmp(s+1,"()")==0||strcmp(s+1,"??")==0)
printf("()\n");
else
printf(":(\n");
}
else
{
printf(":(\n");
}
return 0;
}
if((s[1]=='('||s[1]=='?')&&(s[n]==')'||s[n]=='?')&&(s[2]=='('||s[2]=='?')&&(s[n-1]==')'||s[n-1]=='?'))
flag=1;
if(flag==0)
{
printf(":(\n");
}
else
{
int x,y;
x=y=0;
s[1]=ans[1]='(';
s[2]=ans[2]='(';
s[n]=ans[n]=')';
s[n-1]=ans[n-1]=')';
for(int i=2;i<=n-1;i++)
{
if(s[i]=='?') ans[i]='(',x++;
else if(s[i]=='(') ans[i]='(',x++;
else ans[i]=')',x--;
}
if(x>0)
{
for(int i=n-1;i>=2;i--)
{
if(x&1||x<=0) break;
if(s[i]=='?')
{
x-=2;
ans[i]=')';
}
}
}
if(x==0)
{
int top=0;
int flag=1;
for(int i=2;i<=n-1;i++)
{
if(ans[i]=='(') top++;
else
{
if(top==0)
{
flag=0;
break;
}
top--;
}
}
if(flag)
printf("%s\n",ans+1);
else
printf(":(\n");
}
else
printf(":(\n");
}
}