《劍指offer》 面試題53 :正則表達式匹配 Java


引言:這道題情況比較復雜,邊界條件較多,為了便於以后復習,整理一下。另外,由於C語言和Java對於字符串的操作存在不一樣的地方,代碼也存在改動。

題目:請實現一個函數用來匹配包含'.'和'*'的正則表達式。模式中的字符‘.’表示任意一個字符,而'*'表示它前面的字符可以出現任意次(含0次)。在本題中,匹配是指字符串的所有字符匹配整個模式。例如,字符串"aaa"與模式"a.a"和"ab*ac*a"匹配,但與"aa.a"及"ab*a"均不匹配。

分析:這道題的核心其實在於分析'*',對於'.'來說,它和任意字符都匹配,可把其當做普通字符。對於'*'的分析,我們要進行分情況討論,當所有的情況都搞清楚了以后,就可以寫代碼了。

在每輪匹配中,Patttern第二個字符是'*'時:

  1. 第一個字符不匹配('.'與任意字符視作匹配),那么'*'只能代表匹配0次,比如'ba'與'a*ba',字符串不變,模式向后移動兩個字符,然后匹配剩余字符串和模式
  2. 第一個字符匹配,那么'*'可能代表匹配0次,1次,多次,比如'aaa'與'a*aaa'、'aba'與'a*ba'、'aaaba'與'a*ba'。匹配0次時,字符串不變,模式向后移動兩個字符,然后匹配剩余字符串和模式;匹配1次時,字符串往后移動一個字符,模式向后移動2個字符;匹配多次時,字符串往后移動一個字符,模式不變;

而當Patttern第二個字符不是'*'時,情況就簡單多了

  1. 如果字符串的第一個字符和模式中的第一個字符匹配,那么在字符串和模式上都向后移動一個字符,然后匹配剩余字符串和模式。
  2. 如果字符串的第一個字符和模式中的第一個字符不匹配,那么直接返回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. 

 


免責聲明!

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



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