題意
給出 個長度爲 的字符串, 個長度爲 的字符串,將長度爲 的字符串豎直襬放,長度爲 的字符串水平擺放,問能形成多少個 的矩陣。
如下圖所示, 爲長度爲 的字符串, 爲長度爲 的字符串。
思路
比賽的時候覺得這題很好玩,因爲題意有點繞, 和 老是分不太清。
徹底搞清楚題意後,也沒多少時間了,再加上這題過的人比較少,以爲是道比較難的題,就沒細想…(不過這類數獨題第一反應的確應該是搜索…
賽後看了眼別人的代碼,發現好暴力好簡單…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;
}