题意
给出 个长度为 的字符串, 个长度为 的字符串,将长度为 的字符串竖直摆放,长度为 的字符串水平摆放,问能形成多少个 的矩阵。
如下图所示, 为长度为 的字符串, 为长度为 的字符串。
思路
比赛的时候觉得这题很好玩,因为题意有点绕, 和 老是分不太清。
彻底搞清楚题意后,也没多少时间了,再加上这题过的人比较少,以为是道比较难的题,就没细想…(不过这类数独题第一反应的确应该是搜索…
赛后看了眼别人的代码,发现好暴力好简单…T^T
话不多说,做法就是维护长度为 的字符串的字典树,以及长度为 的字符串的字典树,枚举每一个格子填的字符,从左到右,从上到下依次进行暴力匹配,匹配成功则 …
具体细节可以看看下面的代码,还是不太难理解的。
反思一下,如果早点看懂这道题,正确的思考方式如下:
- 类似数独,感觉是考察搜索
- 怎么搜呢?矩形也不大,要不直接枚举每个节点的字符算了,暴力一发试试水
- 怎么枚举呢?一次性枚举全部肯定是欠 T,要不按顺序从左到右,从上到下枚举试试
- 好像有点道理,那怎么判断当前对不对呢?
- ,涉及字符匹配的数据结构,我想想… 行
- 噢!字典树!妙啊,冲冲冲!
- 恭喜您获得了绿油油的 !
代码
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i = a; i <= b; i++)
const int N = 1e6+10;
using namespace std;
struct Trie{
int tot, root, ch[N][30], pre[N];
Trie() {root = tot = 0;}
void insert(char *str){
int cur = root;
for(int i = 0; str[i]; i++){
int x = str[i]-'a';
if(ch[cur][x] == 0) ch[cur][x] = ++tot, pre[tot] = cur;
cur = ch[cur][x];
}
}
}tre1, tre2;
int n,m,a,b,ans,pos1[10],pos2[10];
char s[N];
void dfs(int id){
if(id == n * m - 1) {ans++; return;}
id++; int row = id / m, col = id % m;
rep(i,0,25){
if(tre1.ch[pos1[col]][i] && tre2.ch[pos2[row]][i]){
pos1[col] = tre1.ch[pos1[col]][i];
pos2[row] = tre2.ch[pos2[row]][i];
dfs(id);
pos1[col] = tre1.pre[pos1[col]];
pos2[row] = tre2.pre[pos2[row]];
}
}
}
int main()
{
scanf("%d%d",&n,&a);
scanf("%d%d",&m,&b);
rep(i,1,a) scanf("%s",s), tre1.insert(s);
rep(i,1,b) scanf("%s",s), tre2.insert(s);
dfs(-1);
printf("%d\n", ans);
return 0;
}