唐纳德先生与 .DOC
题目链接:https://acm.ecnu.edu.cn/contest/126/problem/D/
单测试点时限: 6.0 秒
内存限制: 1024 MB
去年夏天的时候,唐纳德先生就注意到学校饮水机上挂了一个新的牌子:天热冷水需求量大。当时他还不以为意,这不过是一个普通的牌子。于是,天冷了。有一天他注意到牌子上面新增了一个交换的记号。原来,现在牌子要改成「天冷热水需求量大」了,但由于新的标语和旧的标语唯一的区别就是相邻的两个汉字交换了,所以维护人员为了省事儿,就直接在上面做了个记号。
唐纳德先生觉得这件事情很有趣,在自然语言中,交换相邻的两个字符或是单词,产生的句子在语法上仍然说得通这一现象其实并不少见。例如:
唐纳德最近发现交换相邻的单词不一定影响语法上的正确性。
交换「唐纳德」和「最近」,可以变成:
最近唐纳德发现交换相邻的单词不一定影响语法上的正确性。
这句话不仅在语法上合法,在语义上也是等价的。还有在语义上不等价的交换,在语法上也是合法的。例如交换「一定」和「不」:
最近唐纳德发现交换相邻的单词一定不影响语法上的正确性。
为了研究这一问题,唐纳德先生找了大量的语言材料,来分析交换相邻单词对语法合法性的影响。由于一般的自然语言处理常常需要用到大量高深的知识,唐纳德先生选取的语言材料来自一种名为 .DOC 的语言。这种语言的语法具有非常严苛的规则,可以用下面的上下文无关文法表示(其中 s
为开始符号,小写字母都是非终结符):
s ::= d 'O' c d ::= 'D' | '.' s c ::= 'C' | '.' s
现在给出一句合法的句子,要求对于所有可能的相邻字母的交换确认交换后的句子的合法性。
如果读到这里你已经知道怎么做这道题了,你可以跳过剩下的题目描述,直接跳到输入格式。但我还是想再啰嗦几句,以防你完全不知道上下文无关文法是什么。
简单的来说,.DOC 语言只有一种句子结构,就是经典的主谓宾结构。D
表示主语,O
表示谓语,C
表示宾语。例如 DOC
就是一句合法的句子。该语言允许使用主语从句和宾语从句。主语从句以 .
开头,后面是一句合法的句子;宾语从句也是以 .
开头,后面是一句合法的句子。例如 DO.DOC
的宾语是 .DOC
;例如 ..DOCOCOC
也是合法的。对于一句句子,如果你可以用上面所提到的语法规则来解释,那么它就是合法的。
输入
输入第一行是一个整数 t (1≤t≤10^5),表示数据组数。
随后有 t 行,每行一个由 .
, D
, O
, C
组成的字符串 s (3≤|s|≤10^6)。保证这是一句合法的句子。
输入保证所有数据的长度之和不超过 106。
输出
对于每组数据,输出一个长度为 |s|−1 的字符串。字符串的第 i (1≤i≤|s|−1) 个字符表示交换字符串的第 i 个字符和第 i+1 个字符后,字符串是否依然合法。如果合法,该位置填 C
(Correct);如果非法,该位置填 D
(Doomed)。
样例
input
3 DOC DO.DOC ..DOCOCOC
output
DD DDDDD CDDDDDDD
一开始看到这道题直接懵了,这是什么鬼,怎么看不懂。后来发现过的人越来越多,表明这是道水题,然后耐着性子分析了一下,真的水,只要判断相邻的是不是两个点,是,输出C;不是,输出D
首先题目保证所给句子是合法的,合法情况下相邻的有这些情况:.D O. DO OC CO(这个C是主语从句里的) ..
可见,除了..交换位置句子依旧合法之外,其他的都不合法
#include<cstdio>
#include<cstring>
using namespace std;
char s[1000005];
bool judge(int x,int y){
if(s[x]=='.'&&s[y]=='.') return true;
else return false;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%s",s+1);
int l=strlen(s+1);
for(int i=1;i<l;i++){
if(judge(i,i+1)) printf("C");
else printf("D");
}
printf("\n");
}
return 0;
}