1003 Reasoning(大模拟)

原题链接

translation

现有一个推理系统,有如下符号组成:

  • 圆括号:\((\)\()\)
  • 逻辑连词:\(\lnot\)\(\to\)
  • 全称量词:\(\forall\)
  • 变量:\(u-z\)
  • 常量:\(a-e\)
  • 函数:\(f-h\)
  • 谓词:\(P-T\)

这个推理系统还包括项(term)、公式(formula)、自由出现(free occurrence)和替换(replacement)等概念。基于这些概念,我们可以定义某个项 \(t\) 是否可以毫无冲突地替换某个变量 \(x\)。这是推理的基础之一,你想先解决这个问题。

项(term)的定义如下:

  • 所有的变量 \(v\) 是一个项
  • 所有的常量 \(c\) 是一个项
  • 如果 \(t_1,t_2,\dots,t_n\) 是一些项,\(f\) 是一个函数,则 \(f_{t_1,t_2,\dots,t_n}\) 是一个项

公式(formula)的定义如下:

  • 如果 \(t_1,t_2,\dots,t_n\) 是一些项,\(P\) 是一个谓词,则 \(P_{t_1,t_2,\dots,t_n}\) 是一个公式,而且这种公式被称为原子公式(atomic formula)
  • 如果 \(\varphi\)\(\psi\) 都是公式,则 \((\lnot\varphi)\)\((\varphi\to\psi)\) 都是公式
  • 如果 \(\varphi\) 是公式,\(v\) 是变量,则 \(\forall v\varphi\) 是公式

\(x\) 可以在 \(\varphi\) 中自由出现(free occurrence)的定义如下:

  • 如果 \(\varphi\) 是原子公式,\(x\) 可以在 \(\varphi\) 中自由出现当且仅当在 \(\varphi\) 中有 \(x\)(可以理解为字符 \(x\) 在字符串 \(\varphi\) 中出现)
  • 如果 \(\varphi\)\((\lnot\psi)\)\(x\) 可以在 \(\varphi\) 中自由出现当且仅当 \(x\) 可以在 \(\psi\) 中自由出现
  • 如果 \(\varphi\)\((\psi\to\gamma)\)\(x\) 可以在 \(\varphi\) 中自由出现当且仅当 \(x\) 可以在 \(\psi\) 中自由出现或在 \(\gamma\) 中自由出现
  • 如果 \(\varphi\)\(\forall v\psi\)\(x\) 可以在 \(\varphi\) 中自由出现当且仅当 \(x\) 可以在 \(\psi\) 中自由出现且 \(x\neq v\)

对于所有公式 \(\varphi\),变量 \(x\),项 \(t\),替换(replacement)\(\varphi^x_t\) 的定义如下:

  • 如果 \(\varphi\) 是原子公式,那么 \(\varphi^x_t\) 是通过简单地将每个字符 \(x\) 替换为字符串 \(t\) 形成的表达式
  • 如果 \(\varphi\)\((\lnot\psi)\),那么 \((\lnot\psi)^x_t=(\lnot\psi^x_t)\)
  • 如果 \(\varphi\)\((\psi\to\gamma)\),那么 \((\psi\to\gamma)^x_t=(\psi^x_t\to\gamma^x_t)\)
  • 如果 \(\varphi\)\(\forall y\psi\),那么 \((\forall y\psi)^x_t=\left\{\begin{array}{ll}\forall y(\psi^x_t) & & \text{if}\ x\neq y\\\forall y\psi & & \text{if}\ x=y\end{array}\right.\)

最后,无冲突替换的定义如下:

  • 如果 \(\varphi\) 是原子公式,那么 \(t\) 始终可以在 \(\varphi\) 中无冲突替换 \(x\)
  • 如果 \(\varphi\)\((\lnot\psi)\),那么 \(t\)\(\varphi\) 中可以无冲突替换 \(x\) 当且仅当 \(t\)\(\psi\) 中可以无冲突替换 \(x\)
  • 如果 \(\varphi\)\((\psi\to\gamma)\),那么 \(t\)\(\varphi\) 中可以无冲突替换 \(x\) 当且仅当 \(t\)\(\psi\)\(\gamma\) 中都可以无冲突替换 \(x\)
  • 如果 \(\varphi\)\(\forall y\psi\),那么 \(t\)\(\varphi\) 中可以无冲突替换 \(x\) 当且仅当:
    • \(x\) 不能在 \(\varphi\) 中自由出现,或
    • \(y\) 不能在 \(t\) 中自由出现,且 \(t\)\(\psi\) 中可以无冲突替换 \(x\)

现在,你需要判断项 \(t\) 是否可以无冲突替换 \(x\)

solution

模拟即可。

在代码实现上,我忽略了所有 \()\)\(\to\),然后把左括号当做一个有 2 个参数的函数,把 \(\lnot\) 当成一个没有参数的函数,最后把所有变量和常量都当成没有参数的函数,这样整个公式中就只有谓语,函数和 \(\forall\),可以一起实现。

code

#define pb push_back
int T; string s; int m, num[300]; int q; bool v[120][6]; int fa[120];
bool vis[6];
bool IS (char c) {return (c >= 'f' && c <= 'h') || (c >= 'P' && c <= 'T') || (c == '(');}
bool az[120];
void Find (int a, int id) {
	RI i, j; az[id] = 1; int lst = id; for (i = 1; i <= a; ++ i) {
		W (az[id]) ++ id; fa[id] = lst; Find (num[s[id]], id);
	}
}
bool qus[11];
int main () {
	RI i, j; Read (T); W (T --) {
		Mt (fa, -1); Mt (az, 0); Mt (num, 0); Mt (v, 0);
		cin >> s; int n = s.length (); s = " " + s; Read (m);
		for (i = 1; i <= m; ++ i) {char c; int x; Readc (c); Read (x); num[c] = x;} num['('] = 2;
		for (i = 1; i <= n; ++ i) if (s[i] == 'I' || s[i] == ')' || s[i] == 'A' || s[i - 1] == 'A') az[i] = 1;
		for (i = 1; i <= n; ++ i) if (IS (s[i])) {Find (num[s[i]], i); break;}
		bool flag = 0; for (i = 1; i <= n; ++ i) {
			if (s[i] == 'A') {vis[s[i + 1] - 'u'] = 1; ++ i; flag = 1;}
			else if (flag == 1) {for (j = 0; j <= 5; ++ j) v[i][j] |= vis[j]; Mt (vis, 0); flag = 0;} 
		} for (i = 1; i <= n; ++ i) {
			if (fa[i] == -1) continue; for (j = 0; j <= 5; ++ j) v[i][j] |= v[fa[i]][j];
		}
		Read (q); W (q --) {
			string ca; char c; cin >> ca; Readc (c); int len = ca.length (); Mt (qus, 0); 
			for (i = 0; i < len; ++ i) {
				if (ca[i] >= 'a' && ca[i] <= 'e') qus[ca[i] - 'a'] = 1;
				if (ca[i] >= 'u' && ca[i] <= 'z') qus[ca[i] - 'u' + 5] = 1;
			}
			bool YN = 1; for (i = 1; i <= n; ++ i) {
				if (s[i] != c) continue;
				if (fa[i] == -1) continue;
				if (v[i][c - 'u'] == 1) continue;
				for (j = 0; j <= 5; ++ j) {
					if (v[i][j] && qus[j + 5]) {YN = 0; break;}
				}
			}
			putchar (YN ? 'Y' : 'N'); printf ("\n"); if (! YN) continue;
			for (i = 1; i <= n; ++ i) {
				if (s[i] != c) printf ("%c", s[i]);
				else if (v[i][c - 'u'] == 1) printf ("%c", s[i]);
				else if (fa[i] == -1) printf ("%c", s[i]);
				else printf ("%s", ca.c_str ());
			} printf ("\n");
		}
	}
	return 0; 
}
posted @ 2023-08-15 20:17  ClapEcho233  阅读(19)  评论(0编辑  收藏  举报