Scramble String

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.

Below is one possible representation of s1 = "great":

    great

   /    \

  gr    eat

 / \    /  \

g   r  e   at

           / \

          a   t

To scramble the string, we may choose any non-leaf node and swap its two children.

For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".

    rgeat

   /    \

  rg    eat

 / \    /  \

r   g  e   at

           / \

          a   t

We say that "rgeat" is a scrambled string of "great".

Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".

    rgtae

   /    \

  rg    tae

 / \    /  \

r   g  ta  e

       / \

      t   a

We say that "rgtae" is a scrambled string of "great".

Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

开始的思路是类似于二叉树的做法,发现不好找左右子的划分,各种WA,感觉是动态规划,但是我对动态规划不熟悉,没找出状态方程。搜了搜网上的解法,整理了一下:

设f[n][i][j]表示s1中从i位置开始长度为n的串是否与s2中从j位置开始长度为n的串互为scramble string,则有状态方程如下:

f[n][i][j] = f[n][i][j] || (f[k][i][j] && f[n-k][i+k][j+k]) || (f[k][i][j+n-k] && f[n-k][i+k][j])      k从1到n-1

由上述方程可以看出,计算f[n][i][j]时,n之前的已经计算过,i和j之后的已经计算过,因此,递归时候n++,i--,j--。

代码如下:

 1 public boolean isScramble(String s1, String s2) {

 2         int N = s1.length();

 3         if(s1.length()!=s2.length()){

 4             return false;

 5         }

 6         boolean grid[][][] = new boolean[N+1][N][N];

 7         for(int i=0;i<N;i++){

 8             for(int j=0;j<N;j++){

 9                 grid[1][i][j] = s1.charAt(i)==s2.charAt(j);

10             }

11         }

12         for(int n=1;n<=N;n++){

13             for(int i=N-n;i>=0;i--){

14                 for(int j=N-n;j>=0;j--){

15                     for(int k=1;k<n;k++){

16                         grid[n][i][j] = (grid[k][i][j] && grid[n-k][i+k][j+k]) || (grid[k][i][j+n-k] && grid[n-k][i+k][j]);

17                         if(grid[n][i][j]==true){

18                             break;

19                         }

20                     }

21                 }

22             }

23         }

24         return grid[N][0][0];

25     }

复杂度不会算了,从代码的循环上来看是O(n^4),空间复杂度是O(n^3)

感觉还可以改一改,有一个思路,没有具体实现,不知道是否可行

每次在串s1中取子串0到i(i从1到n),与s2中子串的前i个或后i个比较,若字符相同,递归判断是否是scramble string,比较字符相同就先排序,然后比较,排序为O(nlgn),比较为O(n),因此整体为O(nlgn),每次从1到n,因此,为O(n^2*lgn),每次最少可以将s1长度减1,因此,最多递归n次,因此,整体复杂度为O(n^3*lgn)。不知道这么算是否正确,以及复杂度的分析是否正确。

你可能感兴趣的:(String)