/**
主要思路:
    1:难点:如果一个节点被走过,需要标记。但是!当这个节点走不通时,就需要退回来再找另外的路。。这时候问题就来了。当换另外一条路时,其他节点有可能走到刚标记的路上来。这时候原来的标记就需要清楚。
    a b c d
    b c e f
    d r m n
字符串abcbc   开始a(0,0)- b(0,1)-c(1,1)-b(1,0) 然后走不动了
需要退回到 c(1,1) 但是 也不能走动,因为b已经标记了。 所以一直退回到
a(0,0) 然后只有 b(1, 0)要走了,但是此时需要清楚其标记。所以解决方法: 每次标记的限制都是限制前一位的选择,所以保存这个变量。退回时,如果选择了其他位置,该位置标志被清除。或者再退回上一级时,也清除。
**/
import java.util.Stack;
public class Solution {
    public boolean hasPath(char[] mat, int rows, int cols, char[] str){
        if(mat == null || rows < 1 || cols < 1 || rows * cols != mat.length || mat.length < str.length){
            return false;
        }
        Stack<Integer> stack = new Stack<>();
        boolean[] isVis = new boolean[mat.length];//位置访问信息
        int i = 0;
        int j = 0;
        int m = -1;
        while(i < mat.length && j < str.length){
            if(j == 0){  //找第一个位置
                if(!isVis[i] && mat[i] == str[j]){//如果没有访问过且与str对应的相等就入栈
                    stack.push(i); // 入栈
                    if(m > -1){//如果m记录的前一节点的值
                        isVis[m] = false;//清除记忆
                    }
                    isVis[i] = true;
                    j++;
                }else{//否者,继续遍历matrix
                    i++;
                }
            }else{
                int k = stack.peek(); //查看栈顶元素
                if(k - cols >= 0 && !isVis[k - cols] && mat[k - cols] == str[j]){//上一行是否匹配
                    stack.push(k - cols);
                    if(m > -1){//如果m记录的前一节点的值
                        isVis[m] = false;//清除记忆
                    }
                    isVis[k - cols] = true;
                    j++;
                    continue;
                }
                if(k % cols != 0 && !isVis[k - 1] && mat[k - 1] == str[j]){//上一位是否匹配
                    stack.push(k - 1);
                    if(m > -1){//如果m记录的前一节点的值
                        isVis[m] = false;//清除记忆
                    }
                    isVis[k - 1] = true;
                    j++;
                    continue;
                }
                if(k % cols != cols - 1 && !isVis[k + 1] && mat[k + 1] == str[j]){//下一位
                    stack.push(k + 1);
                    if(m > -1){//如果m记录的前一节点的值
                        isVis[m] = false;//清除记忆
                    }
                    isVis[k + 1] = true;
                    j++;
                    continue;
                }
                if(k + cols < mat.length && !isVis[k + cols] && mat[k + cols] == str[j]){//下一行
                    stack.push(k + cols);
                    if(m > -1){//如果m记录的前一节点的值
                        isVis[m] = false;//清除记忆
                    }
                    isVis[k + cols] = true;
                    j++;
                    continue;
                }
                m = stack.pop();  //如果没有找到通路。这个节点就废弃,记录下该点位置。。
                j--; //str的指针也前移重新判断
            }
        }
        return j == str.length; //str遍历完成就表示true了
    }


}