Codeforces 918C/917A - The Monster

传送门:http://codeforces.com/contest/918/problem/C

一个括弧串由字符‘(’和‘)’组成。一个正确的串可被递归地定义,定义如下:

①空串e是一个正确的串;

②若串s是一个正确的串,则串(s)也是一个正确的串;

③若串st均是正确的串,则串st也是一个正确的串。

对于一个由字符‘(’、‘)’和‘?’组成的串s,考虑其子串s.substr(i,j):将这个子串的符号‘?’置换为‘(’或‘)’,若置换后的串是一个正确的串,则原来的子串是一个完美的串。试统计串s中所有的非空完美子串的数目。

这个问题的简单化版本就是括弧匹配,可以通过模拟“栈”以实现:

bool is_correct(const char* ch)
{
    int top = 0; //top of stack
    for (int i = 0; ch[i] != '\0'; i++) {
        if (ch[i] == '(') top++; //open parameter
        else top--; //closed parameter
        if (top < 0) return false;
    }
    if (top == 0) return true;
    return false;
}

接下来,引入符号‘?’,则可以计算top值的上确界sup和下确界inf。将‘?’置换成‘(’,以计算上界;置换成‘)’,以计算下界:

bool is_correct(const char* ch)
{
    int sup = 0, inf = 0;
    for (int i = 0; ch[i] != '\0'; i++) {
        if (ch[i] == '(') sup++, inf++; //open parameter
        else if (ch[i] == ')') sup--, inf--; //closed parameter
        else sup++, inf--;
        if (sup < 0) return false;
        if (inf < 0) inf = 0;
    }
    if (strlen(ch) % 2 == 0)
        if (inf == 0) return true;
    return false;
}

现在考虑本题的问题,则可枚举所有的有序对<i,j>,时间复杂度为O(n2)。参考程序如下:

#include <stdio.h>
#define MAX_L 10000

char ch[MAX_L];

int main(void)
{
    scanf("%s", ch);
    int ans = 0;
    for (int i = 0; ch[i] != '\0'; i++) {
        int sup = 0, inf = 0;
        for (int j = i; ch[j] != '\0'; j++) {
            if (ch[j] == '(') sup++, inf++;
            else if (ch[j] == ')') sup--, inf--;
            else sup++, inf--;
            if (sup < 0) break;
            if (inf < 0) inf = 0;
            if (((j - i) % 2))
                if (inf == 0) ans++;
        }
    }
    printf("%d\n", ans);
    return 0;
}

 

posted on 2018-01-30 20:12  SiuGinHung  阅读(607)  评论(0编辑  收藏  举报

导航