引言:這道題情況比較復雜,邊界條件較多,為了便於以后復習,整理一下。另外,由於C語言和Java對於字符串的操作存在不一樣的地方,代碼也存在改動。
題目:請實現一個函數用來匹配包含'.'和'*'的正則表達式。模式中的字符‘.’表示任意一個字符,而'*'表示它前面的字符可以出現任意次(含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 stub 44 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.
