Regular Expression Matching

  解法一:遞歸spa

  剛開始簡單地覺得掃描字符串,而後對比就好了。但因爲有「*」,沒法考慮全部狀況。所以這題使用了遞歸的方法來解,即不斷地縮短字符串長度,直到分解爲最基礎的幾種狀況。因爲」*"表示重複任意次數,所以應該有一個回溯的過程。固然重複次數最大是帶匹配的字符串的的長度。code

  難度在於基礎狀況的處理以及如何遞歸。基礎狀況須要仔細考慮纔不會遺漏。好比s爲空,p爲空等。代碼以下:blog

 

class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        const char *s_pos=s;
        const char * p_pos=p;
        
        if(*s!='\0'&&*p=='\0')
        return false;

        if(*s=='\0'&&*p=='\0')
            return true;
        if(*s=='\0'&&*p!='\0')
        {
            if(*(p+1)=='*')
                return isMatch(s,p+2);
            return false;
        }
        
        if(*(p+1)!='*')
            return ((*s==*p)||(*p=='.'))&&isMatch(s+1,p+1);
        else
        {
            //caculate the max num of repeating a char
            int c=0;
            while(*(s+c)!='\0')
                c++;

            bool m=true;
            for(int i=0;i<=c;i++)
            {
                //cout<<"i: "<<i<<endl;
                m=true;
                for(int j=0;j<i;j++)
                {
                    bool t=((*(s+j)==*p)||(*p=='.'));
                    //cout<<"i: "<<i<<" j: "<<j<<" "<<t<<endl;
                    if(t==false)
                    {
                        m=false;
                        continue;
                    }
                }
                if(m==false)
                    break;
                else
                {
                    //cout<<"enter next: "<<i<<endl;
                    m=m&&isMatch(s+i,p+2);
                    if(m==true)
                        return true;
                }
            }
        }
        return false;
    }
    

};

   解法二:動態規劃法遞歸

   dp的方法是第二遍回頭作的時候寫的。此時明顯感到思路比之前清晰了不少。。。再次強調,dp最關鍵的是要搞清楚matrix的意義。就此題而言,很是清楚:dp[i][j]表示S的前i個字符與P的前j個字符匹配。字符串

  更新規則:分類考慮,包括p[j]是普通字符,‘.'字符以及'*'字符。前二者更新規則比較清晰;‘*’字符比較麻煩,要分爲重複0次以及重複0次以上。代碼以下:io

  

public class Solution {
    public boolean isMatch(String s, String p) {
        if(s==null||p==null)
            return false;
        int m=s.length()+1;
        int n=p.length()+1;
        boolean dp[][]=new boolean[m][n];
        dp[0][0]=true;
        for(int i=1;i<n;i++)
        {
            if(p.charAt(i-1)=='*')
            {
                if(dp[0][i-2]||dp[0][i-1])
                    dp[0][i]=true;
            }
        }
        for(int i=1;i<m;i++)
        {
            for(int j=1;j<n;j++)
            {
                char sc=s.charAt(i-1);
                char pc=p.charAt(j-1);
                if(pc=='.'||sc==pc)
                {
                    dp[i][j]=dp[i-1][j-1]?true:false;    
                }
                else if(pc=='*')
                {
                    char pre=p.charAt(j-2);
                    if(dp[i][j-2])
                    {
                        //repeat zero time
                        dp[i][j]=true;
                        continue;
                    }
                    if((pre=='.'||pre==sc)&&dp[i-1][j])
                    {
                        //repeat at least one time
                        dp[i][j]=true;
                        continue;
                    }
                }
            }
        }
        return dp[m-1][n-1];
    }
}

  上述代碼中,重複0次和重複屢次的條件分開寫實爲了思路更清晰。由於重複0次是以行爲參考,重複屢次是以列爲參考。ast

  

  網上彷佛有人說用動態規劃方法。DP一直是隻知其一;不知其二,之後考慮再用DP解。class

相關文章
相關標籤/搜索