LeetCode 516.最長迴文子序列

LeetCode 516.最長迴文子序列

區間型動態規劃
確定狀態:
最優策略產生的最長迴文子串是T,長度M
情況一:迴文串長度爲1,即一個字母。
情況二:迴文串長度大於1,那麼必定有T[0]=T[M-1]
T[0]S[i],T[M-1]S[j],剩下的T[1...M-2]仍然是迴文串,而且是S[i+1...j-1]的最長迴文子串。
狀態:f[i][j]S[i..j]的最長迴文子串的長度。

轉移方程:
f[i][j]=max{f[i+1][j],f[i][j-1],f[i+1][j-1]+2(S[i]==S[j])}
初始條件:
一個字母也是一個長度爲1的迴文串:f[0][0]=f[1][1]=...=f[N-1][N-1]=1
如果S[i]==S[i+1],f[i][i+1]=2否則f[i][i+1]=1
計算順序:
區間型動態規劃:按照j-i從小到大的順序計算
長度1:f[0][0],f[1][1]....f[n-1][n-1]
長度2:f[0][1],f[1][2]....f[n-2][n-1]

長度N:f[0][N-1]

class Solution {
    public int longestPalindromeSubseq(String s) {
        char []ch=s.toCharArray();
        int n=ch.length;
        int [][]f=new int [n][n];
        // length:1
        for(int i=0;i<n;i++)
        {
            f[i][i]=1;
        }
        //length:2
        for(int i=0;i<n-1;i++)
        {
            f[i][i+1]= (ch[i]==ch[i+1])?2:1;
        }
        //length >2  
        //Enumeration length
        for(int len=3;len<=n;len++)
        {
            //IMPORTANT: Give attention to the border is equal to n-length
            //Example: len=3
            //0,1,2,3....n-3,n-2,n-1
            //            |
            //          Finish
            for(int i=0,j;i<=n-len;i++)
            {
                j=i+len-1;
                //f[i][j]=MAX{f[i+1][j],f[i][j-1],f[i+1][j-1]+2}
                f[i][j]=Math.max(f[i+1][j],f[i][j-1]);
                if(ch[i]==ch[j])
                    f[i][j]=Math.max(f[i][j],f[i+1][j-1]+2);
            }
        }
        return f[0][n-1];
    }
}

拓展:輸出最長迴文子串
pi[][]用來記錄每一步的操作,從兩側向內掃描。

    public int longestPalindromeSubseq(String s) {
        char []ch=s.toCharArray();
        int n=ch.length;
        int [][]f=new int [n][n];
        int [][]pi=new int[n][n];
        // length:1
        for(int i=0;i<n;i++)
        {
            f[i][i]=1;
        }
        //length:2
        for(int i=0;i<n-1;i++)
        {
            f[i][i+1]= (ch[i]==ch[i+1])?2:1;
        }
        //length >2
        //Enumeration length
        for(int len=3;len<=n;len++)
        {
            for(int i=0,j;i<=n-len;i++)
            {
                j=i+len-1;
                f[i][j]=Math.max(f[i+1][j],f[i][j-1]);
                if(f[i][j]==f[i+1][j])
                    pi[i][j]=0;
                else if(f[i][j]==f[i][j-1])
                    pi[i][j]=1;
                if(ch[i]==ch[j])
                {
                    f[i][j]=Math.max(f[i][j],f[i+1][j-1]+2);
                    pi[i][j]=2;
                }

            }
        }
        char []res=new char[f[0][n-1]];
        int p=0,q=f[0][n-1]-1;
        int i=0,j=n-1;
        while(i<=j)
        {
            if(i==j)
            {
                res[p]=ch[i];
                break;
            }
            if(i+1==j)
            {
                res[p]=ch[i];
                res[q]=ch[j];
                break;
            }
            if(pi[i][j]==0) i++;
            if(pi[i][j]==1) j--;
            if(pi[i][j]==2)
            {
                res[p++]=ch[i++];
                res[q--]=ch[j--];
            }
        }
        System.out.println(String.valueOf(res));
        return f[0][n-1];
    }

記憶化搜索:
將遞歸每個計算過的結果保存。

class Solution {
    int [][]f=null;
    char []ch=null;
    int n=0;
    private void compute(int i,int j)
    {
        if(f[i][j]!=-1)
            return;
        if(i==j)
        {
            f[i][j]=1;
            return;
        }
        if(i+1==j)
        {
            f[i][j]=(ch[i]==ch[j])?2:1;
            return;
        }
        compute(i+1,j);
        compute(i,j-1);
        compute(i+1,j-1);
        f[i][j]=Math.max(f[i+1][j],f[i][j-1]);
        if(ch[i]==ch[j])
        {
            f[i][j]=Math.max(f[i][j],f[i+1][j-1]+2);
        }
    }
    public int longestPalindromeSubseq(String s) {
        ch=s.toCharArray();
        n=ch.length;
        if(n==0)
            return 0;
        if(n==1)
            return 1;
        f=new int [n][n];
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                f[i][j]=-1;
            }
        }
        compute(0,n-1);
        return f[0][n-1];
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章