题意:
给你一个定义为好的字符集合和一个字符串s进行字符匹配。字符s为小写字母、‘*’和‘?’组成。其中‘?’可以任意替换一个好的字符,‘*’可以替换一个由坏的字符组成的串或者去掉‘*’,‘*’最多出现一次。然后给出n个字符串是否匹配。
思路:
直接模拟,要是‘?’就要检查字符是否是为好的字符。要是‘*’就break进行去掉和串的替换两次操作,检查是否成功匹配。
#include <bits/stdc++.h> using namespace std; #define LOCAL typedef long long LL; typedef pair<int, int> PAI; const int INF = 0x3f3f3f3f; const double ESP = 1e-5; const double PI = acos(-1.0); const int MOD = 1e9 + 7; const int MAXN = 1e5 + 100; char s[MAXN], good[MAXN], qs[MAXN]; bool vis[MAXN]; int main(int argc, char const *argv[]) { scanf("%s", good); memset(vis, false, sizeof(vis)); int le = strlen(good); for (int i = 0; i < le; i++) { int t = good[i] - 'a'; vis[t] = true; } scanf("%s", s); int lens = strlen(s); int q; scanf("%d", &q); while (q--) { scanf("%s", qs); int lenq = strlen(qs); int i, j; bool flag = true; bool star = false; for (i = 0, j = 0; i < lenq; i++, j++) { if (s[j] == qs[i]) continue; else if (s[j] == '?' && vis[qs[i] - 'a']) continue; else if (s[j] == '*') {star = true; break;} else flag = false; if (!flag) break; } bool flag1 = true, flag2 = true; if (star) { int i1 = i, j1 = ++j; for (;i1 < lenq; i1++, j1++) { if (s[j1] == qs[i1]) continue; else if (s[j1] == '?' && vis[qs[i1] - 'a']) continue; else flag1 = false; if (!flag1) break; } int i2 = i, j2 = j, t; for (t = 0; t <= lenq - lens; t++) if (vis[qs[i2 + t] - 'a']) {flag2 = false; break;} if (flag2) { i2 += t; for (; i2 < lenq; i2++, j2++) { if (s[j2] == qs[i2]) continue; else if (s[j2] == '?' && vis[qs[i2] - 'a']) continue; else flag2 = false; if (!flag2) break; } } flag = (flag1 and (lenq + 1 == lens)) or (flag2 and (lenq >= lens)); } if (!star && (lens - lenq > 1 || (lens - lenq == 1 && s[i] != '*'))) flag = false; if (flag) printf("YES "); else printf("NO "); } return 0; }
D. Misha, Grisha and Underground
题意:
给你一颗树,每次询问三个节点,任选一个当做终点其他两个为起始点,求两条路径相交的最大值。
思路:
LCA,求出三个相交路径的最大值。(d(a,b) + d(c,b) - d(a,c)) /2 为从a,c出发,到b的相交距离。
#include "bits/stdc++.h" using namespace std; const int maxn = 200100; struct edge { int to, next; }e[2*maxn]; int dp[maxn][30], dis[maxn]; bool vis[maxn]; int fa[maxn], d[maxn*2], head[maxn]; int cnt, num, first[maxn], ver[maxn*2]; void add(int u, int v) { e[num].to = v; e[num].next = head[u]; head[u] = num++; } void dfs(int u, int dep) { vis[u] = true; ver[++cnt] = u; first[u] = cnt; d[cnt] = dep; for (int i = head[u]; i != -1; i = e[i].next) { int v = e[i].to; if (!vis[v]) { dis[v] = dis[u] + 1; dfs(e[i].to, dep + 1); ver[++cnt] = u; d[cnt] = dep; } } } void ST(int n) { for (int i = 1; i <= n; i++) dp[i][0] = i; for (int j = 1; (1<<j) <= n; j++) { for(int i = 1; i+(1<<j)-1 <= n; i++) { int a = dp[i][j-1], b = dp[i+(1<<(j-1))][j-1]; dp[i][j] = d[a] < d[b]?a:b; } } } int RMQ(int l, int r) { int k=0; while((1<<(k+1)) <= r-l+1) k++; int a = dp[l][k], b = dp[r-(1<<k)+1][k]; return d[a]<d[b]? a: b; } int LCA(int u ,int v) { int x = first[u] , y = first[v]; if(x > y) swap(x, y); int res = RMQ(x, y); return ver[res]; } int dist(int x, int y) { int u = LCA(x, y); return dis[x] + dis[y] - 2*dis[u]; } int main(int argc, char const *argv[]) { int n, q; memset(vis, false, sizeof(vis)); memset(head, -1, sizeof(head)); scanf("%d%d", &n, &q); num = 0; for (int u = 2; u <= n; u++) { int v; scanf("%d", &v); add(u, v); add(v, u); } cnt = 0; d[1] = 0; dfs(1,1); ST(2*n-1); while (q--) { int a, b, c, lab, lbc, lac; cin >> a >> b >> c; lab = dist(a, b); lbc = dist(b, c); lac = dist(a, c); int s1 = (lab+lac - lbc)/2+1; int s2 = (lab+lbc - lac)/2+1; int s3 = (lac+lbc - lab)/2+1; int ans = max(s1, max(s2, s3)); printf("%d ", ans); } return 0; }