【题解】CF113A 题解

CF113A 题解

思路分析

模拟题。

首先,我们需要反复多次判断词性,于是可以把它封装成一个函数。

然后我们来逐个满足要求:

  1. 每一个单词都以上述结尾来结尾,也就是说,不以上述的结尾来结尾的单词不符合语法。

这个在输入时就可以判断了,如果判断出词的种类啥也不是,那么就不满足,否则满足。

  1. 一个句子中所有单词的性别必须相同。

这个可以转换为:阴性和阳性不能同时出现。

这个好办,开两个变量记录阴性阳性是否出现过,都出现就不满足,否则满足。

  1. 单独一个合法单词也可以组成一个合法的句子

这个特判一下词数为一的情况就可以了。

  1. 每个句子必须按照以下顺序书写:00 个或多个形容词、11 个名词、00 个或多个动词。

这是难点。

我的思路是:以名词为分界点。

先遍历一遍,找到名词的位置。

然后再在前面和后面扫一遍,判断是否有其它词性的词出现就可以了。

代码

#include <iostream>
#include <string>
#define IL inline
using namespace std;
const int N = 1e5 + 10;

bool g; //词的性别,1阳性,2阴性 
int t; //词的种类,1 形容词,2名词,3动词 
int tp[N]; //每个词的种类 

void counting(string x) //判断一个词的词性 
{
	// x.substr(x.size()-i,i) 代表取 x 的末 i 位 
	if(x.size() >= 3)
	{
		string a = x.substr(x.size() - 3, 3);
		if(a == "etr")
		{
			g = true;
			t = 2;
			return;
		}
	}
	if(x.size() >= 4)
	{
		string b = x.substr(x.size() - 4, 4);
		if(b == "lios")
		{
			g = true;
			t = 1;
			return;
		}
		if(b == "etra")
		{
			g = false;
			t = 2;
			return;
		}
	}	
	if(x.size() >= 5)
	{
		string c = x.substr(x.size() - 5, 5);
		if(c == "liala")
		{
			g = false;
			t = 1;
			return;
		}
	}
	if(x.size() >= 6)
	{
		string d = x.substr(x.size() - 6, 6);
		if(d == "initis")
		{
			g = true;
			t = 3;
			return;
		}
		if(d == "inites")
		{
			g = false;
			t = 3;
			return;
		}		
	} 
	t = -1; //啥也不是 
	return;
}

int main()
{
	int q = 0, cnt = 0;
	bool cxt = false, cxf = false; //阴性是否出现,阳性是否出现 
	string s;
	while(cin >> s)
	{
		counting(s); //判断词性与种类 
		if(t == -1) //不合法(啥也不是) 
		{
			cout << "NO" << endl;
			return 0;
		} 
		else
		{
			cnt++;
			tp[cnt] = t; //记录该词的词性 
			if(g) cxt = true; //阳性 
			else cxf = true; //阴性 
		}
	}
	if(cnt == 1) //单独一个合法单词也可以组成一个合法的句子
	{
		cout << "YES" << endl;
		return 0;
	}
	if(cxt && cxf) //阴性阳性都出现过 
	{
		cout << "NO" << endl;
		return 0;
	}
	int mc = 0;
	int idx = 0;
	for(int i = 1;i <= cnt;i++)
	{
		if(tp[i] == 2) //如果名词 
		{
			mc++; //统计个数 
			idx = i; //记录最后一次出现的位置 
			if(mc >= 2) //多于一个 
			{
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	if(mc == 0) //没有名词 
	{
		cout << "NO" << endl;
		return 0;
	}
	int ct = 0, cq = 0;
	for(int i = 1;i < idx;i++) //在名词前面找 
	{
		cq++; //总词数 
		if(tp[i] == 1)
		{
			ct++; //形容词数 
		}
	}
	if(cq != ct) //名词前面不全是形容词 
	{
		cout << "NO" << endl;
		return 0;
	}
	ct = cq = 0;
	//以下代码逻辑同上 
	for(int i = idx + 1;i <= cnt;i++)
	{
		cq++;
		if(tp[i] == 3)
		{
			ct++;
		}
	}
	if(cq != ct)
	{
		cout << "NO" << endl;
		return 0;
	}
	cout << "YES" << endl;
	return 0;
}
posted @ 2023-07-04 16:41  邻补角-SSA  阅读(12)  评论(0)    收藏  举报  来源