hihocoder 20 展勝地的鯉魚旗


時間限制:10000ms
單點時限:1000ms
內存限制:256MB

描述

巖手縣北上市的「北上市立公園展勝地」,是陸奧國三大櫻花名所之一。每年的四月中旬到五月初,這裏都會舉辦盛大的祭奠。除了可以在盛開的櫻花步道上乘坐觀光馬車徐行、還有橫跨北上川上的鯉魚旗,河畔還有當地特有的爲祭奠祖先而編創的北上鬼劍舞。

假設,我們用一個包含 '(', ')'的括號字符串來區別每面鯉魚旗的方向。一段括號序列被稱爲合法的,當且僅當滿足兩個條件:一、對於整個序列,左括號數量等於右括號;二、對於任意前綴,左括號的數目都不小於右括號的數目。島娘想知道,對於一串括號字符串,有多少子串是合法的,你能幫助她麼。

輸入

輸入數據僅一行,包含一個長度爲 n (1 ≤ n ≤ 106) 的括號字符串。

輸出

輸出一行,表示合法的括號子串的數目。

樣例輸入
(()())
樣例輸出
4


題解:

本題 O(n) 的做法很多。

做法一:

考慮平衡的子串一定是 (...)(...)(...) 結構的,一種方法時,從左向右掃一遍, 對於每個左括號 i,嘗試匹配一個右括號 pi,(如果沒有匹配設 pi 爲 -1) 初始每個左括號設爲沒有被標記,順序枚舉沒被標記的有匹配的左括號 i,標記它,然後看 pi+1 位置是不是有匹配的左括號,如果是,標記它,然後重複上述操作,這樣得到一系列合法的括號,它們互不相交,但是相連,比如說有k個,那麼對應着k*(k+1)/2個平衡的子串。 因爲每個括號只會被標記一次,因此複雜度爲 O(n)。

方法二,考慮動態規劃 F[i] 代表以第 i 個字符爲結尾的平衡串個數, 預處理出每個與右括號匹配的左括號 j,如果存在的話, 那麼 f[i]=f[j]+1; 複雜度也是 O(n)。



#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn=1000006;
char s[maxn];
int st[maxn],dp[maxn];

int main()
{
    int top=-1;
    long long sum=0;
    scanf("%s",s);
    int len=strlen(s);
    for (int i=0;i<len;i++)
    {
        if (s[i] == '('){
            st[++top]=i;
        }else{
            if (top != -1)
            {
                int pre=st[top];
                dp[i]=1;
                if (pre != 0)
                    dp[i]+=dp[pre-1];
                top--;
            }
        }
        sum+=dp[i];
    }
    printf("%lld",sum);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章