语言【模拟】

Description–

牛妹正在学习一种新的语言,在这种语言里,单词只有形容词 ( A ) (A) (A),名词 ( N ) (N) (N) 和动词 ( V ) (V) (V) 三种词性。但是一个单词可以对应多种词性。一个名词性词组 ( N P ) (NP) (NP) 可以由一个名词 ( N ) (N) (N),或者一个形容词修饰一个子名词性词组 ( A + N P 1 ) (A+NP1) (A+NP1),或者两个子名词性词组 ( N P 1 + N P 2 ) (NP1+NP2) (NP1+NP2) 组成。即 N P   : =   N   ∣   A + N P 1   ∣   N P 1 + N P 2 NP\ :=\ N\ |\ A+NP_1\ |\ NP_1+NP_2 NP := N  A+NP1  NP1+NP2

一个句子 ( S ) (S) (S) 必须由一个名词性词组 ( N P 1 ) (NP1) (NP1) 加一个动词 ( V ) (V) (V) 再加一个名词性词组 ( N P 2 ) (NP2) (NP2) 组成,即 S : = N P 1 + V + N P 2 S := NP_1+V+NP_2 S:=NP1+V+NP2

牛妹用这个语言写下一个单词的序列,现在你想知道这个单词序列是否能通过适当安排序列里每个单词的词性使之成为一个句子(不同位置的相同的单词也可以安排不同的词性)。

为了简单起见,她把每个单词编码对应为一个小写拉丁字母,不同的单词对应不同的字母(这里我们假设序列里面不同的单词的总数不超过 26 26 26 个)。每个单词用 1 ( 001 ) 1(001) 1(001) 7 ( 111 ) 7(111) 7(111) 来表示这个单词的词性。数字的二进制第 1 1 1 位为 1 1 1 表示是 A A A(形容词),否则表示不是 A A A;第 2 2 2 位为 1 1 1表示是 N N N(名词),否则表示不是 N N N;第 3 3 3 位为 1 1 1 表示是 V V V(动词),否则表示不是 V V V

在这里插入图片描述


Input–

第一行 T T T,代表测试样例的个数。
对于每个测试样例,一行, 26 26 26个正整数 w a , w b , . . . , w z w_a,w_b,...,w_z wa,wb,...,wz,表示每个单词的词性。
接下来一行,一个字符串 S S S,表示单词序列,保证 S S S 中只包含小写字母。

Output–

对于每组样例,如果能构成一个句子,输出 “ Y e s ” ; “Yes”; Yes否则输出 “ N o ” 。 “No”。 No


Sample Input–

样例1

1
7 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
bcaa

样例2

1
7 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
abca

Sample Output–

样例1

Yes

样例2

No

说明–

样例1
首先 a a a 可以是 A A A N N N V V V b b b 只能是 A A A c c c 只能是 N N N
b b b A A A c c c N N N b c bc bc 构成 N P NP NP;前面一个 a a a V V V ;后面一个 a a a N N N,单独构成 N P NP NP,符号 N P + V + N P NP+V+NP NP+V+NP 的结构,因此可以是一个句子。

样例2
可以验证,不管怎么给单词安排词性,都无法构成 N P + V + N P NP+V+NP NP+V+NP 的结构,所以不可能是一个句子。

数据范围
对于 30 % 30\% 30% 数据,满足 1 ≤ ∣ S ∣ ≤ 1000 1\leq |S|\leq 1000 1S1000
对于 100 % 100\% 100% 数据,满足 T = 10 , 1 ≤ ∣ S ∣ ≤ 100000 , 1 ≤ w X ≤ 7 , X ∈ { a , b , . . . , z } T=10, 1\leq |S|\leq 100000, 1\leq w_X \leq 7, X\in \left\{a,b,...,z\right\} T=10,1S100000,1wX7,X{a,b,...,z}


解题思路–

  • 显然有 2 2 2 个或以上的只能为 V V V 的不合法
  • 每个 N P NP NP 必为 N N N 结尾
  • 唯一的 V V V 不在开头或结尾

代码–

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int t, g, w, len, a[30];
bool pd[100005];
string s;

void work()
{
	for (int i = 0; i < 26; ++i)
	  scanf("%d", &a[i]);
    cin >> s;
	len = (int)s.size() - 1;
	g = 0, w = len;
	if (!(a[s[len] - 'a'] & 2))
	{
		printf("No\n");
		return ;
	}
	for (int i = 0; i <= len; ++i)
	  if (!(a[s[i] - 'a'] & 3))
	  {
		  if (!g) w = i, g = 1;
		  break;
	  }
	for (int i = len - 1; i >= 1; --i)
	{
		if ((a[s[i] - 'a'] & 4) && (i - 1 < w) && (a[s[i - 1] - 'a'] & 2))
		{
			printf("Yes\n");
			return ; 
		}
		if (!(a[s[i] - 'a'] & 3))
		  break;
	}
	printf("No\n");
}

int main()
{
	scanf("%d", &t);
	for (int i = 1; i <= t; ++i)
	  work();
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值