E - Petya and Exam
这个题目其实可以不用字典树写,但是因为之前写过poj的一个题目,意思和这个差不多,所以就用字典树写了一遍。
代码还是很好理解的,主要就是哪个findx函数,这个要好好理解。
如果碰到*或着?就要重新标记一下,其他都是一样的,对于?可以跳过好字母,对于*可以跳过若干个不好的字母,
这个就在直接跳过之前加一个判断条件就可以了。
贴一下代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<iomanip> #define INF 99999999 using namespace std; const int maxn = 1e5 + 10; typedef long long ll; int tree[maxn][30], tot = 0, ans, isgood[1000]; bool flag[maxn]; char good[30], s[maxn], str[maxn]; int add(char *s) { int root = 0, id, len = strlen(s); for (int i = 0; i < len; i++) { if (s[i] == '*') id = 26; else if (s[i] == '?') id = 27; else id = s[i] - 'a'; if (!tree[root][id]) tree[root][id] = ++tot; root = tree[root][id]; // printf("root=%d s=%c ", root, s[i]); } flag[root] = true; return root; } void findx(char *s, int root, int pos) { // printf("%s root=%d pos=%d ", s, root, pos); int len = strlen(s); if (pos > len) return; if (len == pos && flag[root]) { ans = 1; return; } if (tree[root][26]) { int flag = 1; int len1 = strlen(str) - 1; int ends = len1 - pos; // printf("ends=%d len-ends=%d pos=%d ", ends, len - ends-1, pos); for (int i = pos; i <= len - ends - 1; i++) { int id = s[i] - 'a'; if (isgood[id]) { flag = 0; break; } } // printf("flag=%d pos=%d len-ends=%d ", flag, pos, len - ends); if (flag&&len - ends >= pos) findx(s, tree[root][26], len - ends); // for (int j = pos; j <= len; j++) { // int id = s[j] - 'a'; // if (isgood[id]) break; // findx(s, tree[root][26], j + 1); // } } if (tree[root][27]) { int length = strlen(good); for (int i = 0; i < length; i++) { if (s[pos] == good[i]) findx(s, tree[root][27], pos + 1); } } int id = s[pos] - 'a'; if (s[pos] <= 'z'&&s[pos] >= 'a'&&tree[root][id]) findx(s, tree[root][id], pos + 1); } int main() { scanf("%s%s", good, str); int len = strlen(good); for (int i = 0; i < len; i++) { int id = good[i] - 'a'; isgood[id] = 1; } int num = add(str); int m; scanf("%d", &m); while (m--) { scanf("%s", s); ans = 0; findx(s, 0, 0); if (ans) printf("YES "); else printf("NO "); } return 0; }
Wild Words poj 1816
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<iomanip> #define INF 99999999 using namespace std; const int maxn = 2e6 + 10; typedef long long ll; int tree[maxn][30], tot = 0, ans, p[maxn]; bool flag[maxn], vis[maxn]; char s[maxn], str[maxn]; int add(char *s) { int root = 0, id, len = strlen(s); for (int i = 0; i < len; i++) { if (s[i] == '*') id = 26; else if (s[i] == '?') id = 27; else id = s[i] - 'a'; if (!tree[root][id]) tree[root][id] = ++tot; root = tree[root][id]; } flag[root] = true; return root; } void findx(char *s, int root, int pos) { // printf("%s root=%d pos=%d ", s, root, pos); int len = strlen(s); if (pos > len) return; if (len == pos && flag[root]) { vis[root] = 1; } if (tree[root][26]) { for (int i = pos; i <= len; i++) findx(s, tree[root][26], i); } if (tree[root][27]) findx(s, tree[root][27], pos + 1); int id = s[pos] - 'a'; if (s[pos] <= 'z'&&s[pos] >= 'a'&&tree[root][id]) findx(s, tree[root][id], pos + 1); } vector<int>res; int main() { int n, m; scanf("%d%d", &n, &m); for(int i=1;i<=n;i++) { scanf("%s", str); p[i]=add(str); } while(m--) { scanf("%s", str); findx(str, 0, 0); res.clear(); for(int i=1;i<=n;i++) if (vis[p[i]]) res.push_back(i - 1); int len = res.size(); if (len == 0) printf("Not match "); else { for (int i = 0; i < len - 1; i++) printf("%d ", res[i]); printf("%d ", res[len - 1]); } for (int i = 1; i <= n; i++) vis[p[i]] = 0; } return 0; }