ACM-括號匹配問題


  對ACM仰慕已久,無奈今天才開始。好吧,遇到的第二個題目就把我難到了。(實話是第一個)

  進入正題,下面Copy出題目:

  

 現在,有一行括號序列,請你檢查這行括號是否配對。
輸入
第一行輸入一個數N(0<N<=100),表示有N組測試數據。后面的N行輸入多組輸入數據,每組輸入數據都是一個字符串S(S的長度小於10000,且S不是空串),測試數據組數少於5組。數據保證S中只含有"[","]","(",")"四種字符
輸出
每組輸入數據的輸出占一行,如果該字符串中所含的括號是配對的,則輸出Yes,如果不配對則輸出No
樣例輸入
3
[(])
(])
([[]()])
樣例輸出
No
No
Yes

拿到該題目的時候,想的最多的當然是括號匹配的問題,並沒有思考其他的。以下是我思考的過程:
隨便寫一個很長的括號匹配的例子來找到其中的規律。如下:
[([()])()]

欣喜若狂,找到了如下的規律:
======================================================================================================
1.如果這個字符串的長度為奇數,不用看了,這個字符串已經不可能匹配了。所以會用到strlen()函數。
2.對於滿足偶數條件的,那就從第一個字符開始查找。先找第一個,再找第二個:
  若第一個和第二個不匹配,表明從最后一個括號肯定是匹配的,所以開始匹配判斷。(以此類推)。
======================================================================================================

當深入分析的時候,發現,好吧,該模型太理想化了,不行。存在嚴重的錯誤,只有當該括號完全中心軸對稱才會滿足這種情況,PASS。


所以,我又想了一下其他的,終於,考慮到遞歸+消除的思想,想到了一個絕佳的點子:
=======================================================================================================
1.遞歸-->解析到最小解;
2.消除-->匹配以后我就不用管了。
===========================================================================

在括號匹配中,總會有這種情況出現:()或[]。當把這一部分消除以后,剩下的部分也總是會出現()或[]。
那么,是否可以將此作為一個單位消除掉,直到最后整個序列全部消除?我想應該是可以的。
但是,如何去實現這一部分?采用什么方式去實現,又是一個頭疼的問題。
這讓我聯想到了播放音樂時候的“節奏條”(姑且這么稱呼吧),可以大,可以小,最后可以沒有。
所以,我需要兩個部分。
1.字符串首地址指針。
2.移動指針。
總覺得少了一點什么,怎么去表示刪除的字符呢?在原字符串中可以表示嗎?又是一個難題。需要去解決,於是想到了其他的解決方案:
將字符串序列中的第一位開始,一個一個判斷,利用"FILO"的方式進行表示,所以就有了如下的思路:

==================================================================================================
1.將元素一個一個壓棧,若將要入棧的元素和棧頂元素匹配,那么彈出棧頂元素。
2.遍歷整個字符串,當遍歷完了以后,判斷當前棧底,棧頂都在哪里。如果相等,說明匹配,否則。
=======================================================================

為什么要遍歷完?這是一個問題!!為什么不能再中途引進錯誤判斷機制呢?所以,就有了如下的思考:
將這些匹配元素,我們可以分為兩類:
一類為左,一類為右。(這不是廢話嗎?)
書面一點:一類為起始符,一類為結束符
規則是這樣的:

================================================
有了起始符,才會出現結束符!
================================================


但檢測到將入棧的元素和棧頂元素不為同一類,並且不匹配。那么,我們就有權去說:
不用查了,這個字符串打死我,我也會說No.

如果說,棧操作深奧了,可以利用外部數組(就是數組)的方式來作為刪除元素的緩存Buff。

那么,就有了如下的思考:
===============================================================================================
1.判斷當前字符串的長度。
2.將字符串從第一個字符拷貝到Buff中。
3.錯誤判斷機制,若在不同類,並且匹配,那么將當前所在的索引處的值初始化,並將數組元素的動態索引值-1.
4.期間,沒有錯誤,並且處理完當前字符串,否則No.
5.ok,沒有問題,返回YES。
=====================================================================================

以上,只是解決了字符串的匹配問題,還有輸出呈現問題。
輸出呈現,是全部遍歷完成字符串數組以后,然后再輸出的,所以需要有一個緩存Buff,存儲當前結果是YES or No。
===============================================================
最簡單的,就算是用for循環遍歷這個數組了,0為No,1為YES.
===============================================================

好的,已經解決了提設的問題,但是,想想該問題還是簡單化了!
=====================================================================================
  1. 如果是3對匹配,4對匹配呢?
  2. 是否需要考慮封裝的問題?將匹配函數封裝,滿足支持動態擴展的形式進行擴展,而不是固定匹配()和[].
  3. 如果中間存在其他值,而不是單獨的字符,該如何處理?忽略掉非匹配字符類?然后按照類似的方法進行。
  4. …………其他
=================================================================================================

以上,便是思考的全部過程,有錯誤,有修正,覺得對思考有幫助,便記錄下來。

以下便是代碼了,相信0基礎的童鞋應該都可以看懂吧。

  1 #include <stdio.h>
  2 #include <string.h>
  3 
  4 int Judge_Sts(char* str,int length);
  5 int Judge_Type(char Name);
  6 int Match_Char(char Start,char End);
  7 
  8 int main(void)
  9 {
 10     /*局部變量定義*/
 11     int Num;
 12     int Index;
 13     int Str_Length;
 14     char Temp[10000];
 15     char OutFlag[100];
 16     char bflag;
 17     /* 獲取行數 */
 18     scanf("%d",&Num);
 19     /* 循環處理 */
 20     for(Index = 0;Index < Num; Index++)
 21     {
 22         scanf("%s",&Temp);
 23         /* 判斷長度 */ 
 24         Str_Length = strlen(Temp);
 25         /* 奇數 */
 26         if(Str_Length&1)
 27         {
 28             OutFlag[Index] = 0;
 29         }
 30         else
 31         {
 32             /* 偶數就開始判斷 */ 
 33             OutFlag[Index] = Judge_Sts(Temp,Str_Length);
 34         }
 35     }
 36     /* 輸出YES or NO */ 
 37     for(Index = 0; Index < Num; Index++)
 38     {
 39         if(OutFlag[Index])
 40         {
 41             printf("YES\n");
 42         }
 43         else
 44         {
 45             printf("NO\n");
 46         }
 47     }
 48 }
 49 
 50 /* 判斷字符串 */
 51 /*
 52 *    不匹配:0    
 53 *    匹配:1 
 54 */ 
 55 int Judge_Sts(char* str,int length)
 56 {
 57     int i;
 58     char* TagStr = NULL;
 59     int Bret = 1;
 60     char Temp;
 61     int Str_Top = 0;
 62     
 63     TagStr = str;
 64     for(i = 0; i < length; i++)
 65     {
 66         Temp = *(str+i);
 67         if(Judge_Type(Temp))
 68         {
 69             if(Str_Top == 0)
 70             {
 71                 Bret = 0;
 72                 break;
 73             }
 74             else
 75             {
 76                 Str_Top--;
 77                 if(Match_Char(*(TagStr+Str_Top),Temp))
 78                 {
 79                     ;
 80                 }
 81                 else
 82                 {
 83                     Bret = 0;
 84                     break;
 85                 }
 86             }
 87         }
 88         else
 89         {
 90             *(TagStr+Str_Top) = *(str+i);
 91             Str_Top++;
 92         }
 93     }
 94     
 95     if(Str_Top)
 96     {
 97         Bret = 0;
 98     }
 99     else
100     {
101         Bret &= 1;
102     }
103     return (Bret);
104 }
105 
106 /* 判斷該字符屬於哪一種,開始字符 or 結束字符 */
107 /*
108 *    開始符:0 
109 *    結束符:1 
110 */ 
111 int Judge_Type(char Name)
112 {
113     int bRet = 1;//默認需要和前一個判斷 
114     switch(Name)
115     {
116         case '(':
117         case '[':
118             bRet = 0;
119             break;
120         case ')':
121         case ']':
122             bRet = 1;
123             break;
124         default:
125             break;
126     }
127     
128     return (bRet);
129 }
130 
131 /* 判斷是否匹配 */
132 int Match_Char(char Start,char End)
133 {
134     int a;
135     if((Start == '(' && End == ')') || (Start == '[' && End == ']') )
136     {
137         a = 1;
138     }
139     else
140     {
141         a = 0;
142     }
143     return a;
144 }

 

(PS:有時間在想出一些巧妙的方法出來吧。先這樣了。)




















 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM