C. The Monster 括号匹配

The Monster
题目大意:
给出一个串,只包含 ( ? ) 三种符号,求出有多少个子串是完美匹配的.
比如

( ) ? )  =>  ( ) ( ) 完美匹配
( ( ) ? => ( ( ) )完美匹配
? ? ? ? => ( ) ( )
     => ( ( ) )
     算一种子串

length<5000 ,1000ms
分析:
这个长度和时间限制比较诡异,想不到比较好的方法,猜想应该是在 n2 上的基础上做一点优化.结果确实是这样的
枚举两个端点没有试过,可能会超时
枚举起点开始往后遍历,做标记

if  ( 
    cnt++
else if  ) 
    cnt--
else 
    f++
    cnt++

先把 ? 当 ( 算
如果 ) 太多了 break
如果 ? 可以取到值 使得这个子串成立, 答案++;
这样就做完了

并没有
少了关键的一步没做出来… 如果仅仅是按照这样小关系来算会出现错误
原因在于每次得到的都是当前位置的最终结果 并不知道先后顺序 使得 ? ( 和 ( ? 的处理情况一样 都会使得答案+1
但是先后顺序是没法得到的,怎么避免 ? ( 的情况呢
容易想到 ? ( 中 ? 不可能是未知量 而是确定的 (
在判断的之前先把能确定下的 ? 全部确定下来,剩下的全是可变的 ? ,再判断能否按照题目要求变化即可.

具体实现:

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define inf 0x3f3f3f3f
#define mem(s,t) memset(s,t,sizeof s)
typedef pair<int,int> pii;
typedef long long ll;
const int MAXN =1e5+10;
int main() {
    string s;
    cin>>s;
    int cnt=0,f=0,ans=0;
    for(int i=0;i<s.size();i++){
        cnt=0,f=0;
        for(int j=i;j<s.size();j++){
            if(s[j]=='('){
                cnt++;
            }
            else if(s[j]==')'){
                cnt--;
            }
            else {
                f++;
                cnt++;
            }
            if(cnt<0) break;
            f=min(f,cnt/2);//最多需要 cnt/2个 的 ?来参与变化 其他的?都是可确定量
            if(cnt%2==0 && cnt/2<=f) ans++;//长度为偶数  && 可以取到 cnt/2的值
        }
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/joovo/article/details/79206873
今日推荐