標籤:void pac 多次 試題 system.in 注意 鍵盤輸入 int sys
引言:這道題情況比較複雜,邊界條件較多,為了便於以後複習,整理一下。另外,由於C語言和Java對於字串的操作存在不一樣的地方,代碼也存在改動。
題目:請實現一個函數用來匹配包含‘.‘和‘*‘的Regex。模式中的字元‘.’表示任意一個字元,而‘*‘表示它前面的字元可以出現任意次(含0次)。在本題中,匹配是指字串的所有字元匹配整個模式。例如,字串"aaa"與模式"a.a"和"ab*ac*a"匹配,但與"aa.a"及"ab*a"均不匹配。
分析:這道題的核心其實在於分析‘*‘,對於‘.‘來說,它和任一字元都匹配,可把其當做一般字元。對於‘*‘的分析,我們要進行分情況討論,當所有的情況都搞清楚了以後,就可以寫代碼了。
在每輪匹配中,Patttern第二個字元是‘*‘時:
- 第一個字元不匹配(‘.‘與任一字元視作匹配),那麼‘*‘只能代表匹配0次,比如‘ba‘與‘a*ba‘,字串不變,模式向後移動兩個字元,然後匹配剩餘字串和模式
- 第一個字元匹配,那麼‘*‘可能代表匹配0次,1次,多次,比如‘aaa‘與‘a*aaa‘、‘aba‘與‘a*ba‘、‘aaaba‘與‘a*ba‘。匹配0次時,字串不變,模式向後移動兩個字元,然後匹配剩餘字串和模式;匹配1次時,字串往後移動一個字元,模式向後移動2個字元;匹配多次時,字串往後移動一個字元,模式不變;
而當Patttern第二個字元不是‘*‘時,情況就簡單多了:
- 如果字串的第一個字元和模式中的第一個字元匹配,那麼在字串和模式上都向後移動一個字元,然後匹配剩餘字串和模式。
- 如果字串的第一個字元和模式中的第一個字元不匹配,那麼直接返回false。
好,現在思路已經清楚了,可以看代碼了:
1 package test; 2 import java.util.Scanner; 3 4 public class Question_53 { 5 public static boolean match(String input,String pattern){ 6 if(input==null||pattern==null) return false; 7 return matchCore(input,0,pattern,0); 8 } 9 private static boolean matchCore(String input,int i,String pattern,int p){10 if((input.length()==i)&&(pattern.length()==p)){11 //出口1,input和pattern都到了字串末尾12 return true;13 }14 if((i!=input.length())&&(pattern.length()==p)){15 //出口2,字串input沒有到末尾,pattern到了末尾16 return false;17 }18 if((input.length()==i)&&(pattern.length()!=p)){19 //出口3,字串input到末尾,pattern還沒有到末尾20 return false; 21 }22 23 if((p+1<pattern.length())&&(pattern.charAt(p+1)==‘*‘)){//pattern第二個字元為*24 if((input.charAt(i)==pattern.charAt(p))||(pattern.charAt(p)==‘.‘)){25 //首字母相匹配26 return matchCore(input,i+1,pattern,p+2) //*表示出現1次27 ||matchCore(input,i+1,pattern,p) //*表示出現多次28 ||matchCore(input,i,pattern,p+2); //*表示出現0次 , a ... p* ...29 }else{30 //首字母不匹配31 return matchCore(input,i,pattern,p+2);32 }33 } //end pattern.charAt(p+1)==‘*‘34 35 if((input.charAt(i)==pattern.charAt(p))||(pattern.charAt(p)==‘.‘)){36 //pattern第二個字母不是*,且首字母匹配37 return matchCore(input,i+1,pattern,p+1);38 }39 return false; //其餘情況全部不匹配40 }41 42 public static void main(String[] args) {43 // TODO Auto-generated method stub44 Scanner scanner = new Scanner(System.in); //掃描鍵盤輸入 45 System.out.println(" 請輸入第一個字串:"); 46 String str1 = scanner.nextLine(); 47 System.out.println(" 請輸入第二個字串:"); 48 String str2 = scanner.nextLine();49 scanner.close();50 51 System.out.print("匹配的結果為:"); 52 System.out.println(match(str1, str2)); 53 }54 55 }
注意邊界條件,當模式和字串都只剩一個字元時, pattern.charAt(p+1)==‘*‘ 會訪存越界,所以需要加額外的限制條件 p+1<pattern.length() ,這樣這個條件不能滿足就會進入下一個if判斷語句,直接判斷兩個字元是不是相等,最後進入出口1,返回true。字串和模式任意一個先結束都視作不匹配,返回false,這就是出口2和出口3.
《劍指offer》 面試題53 :Regex匹配 Java