題意:
給你一個包含'(',')','?'的字符串。然後定義嚴格前綴,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");
}
}