单词搜索 II

单词搜索 II

给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words返回所有二维网格上的单词

单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

示例 1:

img

输入:board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
输出:["eat","oath"]

示例 2:

img

输入:board = [["a","b"],["c","d"]], words = ["abcb"]
输出:[]

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 12
  • board[i][j] 是一个小写英文字母
  • 1 <= words.length <= 3 * 104
  • 1 <= words[i].length <= 10
  • words[i] 由小写英文字母组成
  • words 中的所有字符串互不相同

代码:

//dfs回溯+tire树剪枝

class Solution {
 public:
  int son[100010][26]={0},cent[100010]={0},idx=0;
    //四个搜索方向
  int dp[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};  
  int n, m;
  vector<string> res;
 //构建字典树
  void insert(string word) {  
     int p=0;
     for(auto i:word){
         int u=i-'a';
         if(son[p][u]==0)  son[p][u]=++idx;
         p=son[p][u];
     }
     cent[p]++;
    }

  void dfs(vector<vector<char>>& board, int i, int j, string tmp,int id) {
        if (i < 0 || j < 0 || i >= n || j >= m)  return;
			  
		    char c = board[i][j];
        int u = c - 'a';
        //是否用过则剪枝
        if(c == '*' || son[id][u]==0) {  
            return;
        }
        id=son[id][u];
        //是单词放到res中,并从字典树剔除
        if(cent[id]>=1) {
            res.push_back(tmp+c);
            cent[id]= 0;
        }
        
        board[i][j] = '*';//标记已经访问过

        //上、下、左、右四个方向遍历
        for(int k =0; k<4; k++)
            dfs(board, i+dp[k][0], j+dp[k][1], tmp + c,id);
        
		    board[i][j] = c; //回溯
        
        return;
    }

  vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
    n = board.size(), m = board[0].size();
    
    for(auto z:words)
    insert(z);

    for (int i = 0; i < n; i++)  //从每个起点开始寻找,是否有满足的单词
			for (int j = 0; j < m; j++)
				dfs(board, i, j, "",0);	

    return res;
  }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值