Mihai plans to watch a movie. He only likes palindromic movies, so he wants to skip some (possibly zero) scenes to make the remaining parts of the movie palindromic.
You are given a list ss of nn non-empty strings of length at most 33, representing the scenes of Mihai's movie.
A subsequence of ss is called awesome if it is non-empty and the concatenation of the strings in the subsequence, in order, is a palindrome.
Can you help Mihai check if there is at least one awesome subsequence of ss?
A palindrome is a string that reads the same backward as forward, for example strings "z", "aaa", "aba", "abccba" are palindromes, but strings "codeforces", "reality", "ab" are not.
A sequence aa is a non-empty subsequence of a non-empty sequence bb if aa can be obtained from bb by deletion of several (possibly zero, but not all) elements.
Input
The first line of the input contains a single integer tt (1≤t≤1001≤t≤100) — the number of test cases. The description of test cases follows.
The first line of each test case contains a single integer nn (1≤n≤1051≤n≤105) — the number of scenes in the movie.
Then follows nn lines, the ii-th of which containing a single non-empty string sisi of length at most 33, consisting of lowercase Latin letters.
It is guaranteed that the sum of nn over all test cases does not exceed 105105.
Output
For each test case, print "YES" if there is an awesome subsequence of ss, or "NO" otherwise (case insensitive).
Example
input
6
5
zx
ab
cc
zx
ba
2
ab
bad
4
co
def
orc
es
3
a
b
c
3
ab
cd
cba
2
ab
ab
output
YES
NO
NO
YES
YES
NO
Code
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 100005;
const int MAX_BK = 700;
const int MAX_BK1 = 20005;
int n;
char s[MAXN][5];
bool bk[MAX_BK] = {0};
bool bk1[MAX_BK1] = {0};
int readint() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
int main() {
int T = readint();
while (T--) {
n = readint();
for (int i = 1; i <= n; i++) {
scanf("%s", s[i]);
}
bool fl = false;
memset(bk, 0, sizeof(bk));
memset(bk1, 0, sizeof(bk1));
for (int i = 1; i <= n; i++) {
int l = strlen(s[i]);
if (l == 1) {
fl = true;
} else if (l == 2) {
int idx = (s[i][0]-'a') * 26 + (s[i][1]-'a');
if (bk[idx]) {
fl = true;
}
for (int j = 0; j < 26; j++) {
int idx1 = j * 26 * 26 + (s[i][0]-'a') * 26 + (s[i][1]-'a');
if (bk1[idx1]) {
fl = true;
}
}
bk[idx] = true;
} else if(l == 3){
int idx = (s[i][1]-'a') * 26 + (s[i][2]-'a');
int idx1 = (s[i][0]-'a') * 26 * 26 + (s[i][1]-'a') * 26 + (s[i][2]-'a');
if (bk[idx] || bk1[idx1]) {
fl = true;
}
bk1[idx1] = true;
}
}
if (fl) {
printf("YES\n");
} else {
printf("NO\n");
}
}
return 0;
}
Conclusion
首先,代码中定义了一些常量和全局变量,包括MAXN、MAX_BK、MAX_BK1作为数组的最大容量;n表示测试样例的数量;s是一个字符数组,用来存储输入的字符串;bk和bk1是用来记录字符串出现情况的布尔数组。
接下来,代码实现了一个readint函数,用于读取整数输入。
主函数main中通过调用readint函数读取测试样例的数量,并进行循环处理每个测试样例。
在每个测试样例中,通过调用readint函数读取样例中字符串的数量n,然后使用scanf函数读入每个字符串。
之后,定义了一个布尔变量fl用于表示是否满足特定条件。
使用memset函数将bk和bk1数组初始化为0。
进入一个循环,遍历每个字符串。首先,获取当前字符串的长度l。根据字符串的长度,判断可能出现的情况:
如果l为1,表示字符串长度为1,直接将fl设置为true。
如果l为2,根据字符串的前两个字符计算出一个索引idx,用于记录该字符串的出现情况。判断如果bk[idx]为true,说明之前已经出现过相同的字符串,将fl设置为true。然后,通过一个循环遍历26个字符,计算出另外一个索引idx1,判断如果bk1[idx1]为true,说明之前已经出现过相同的字符串,将fl设置为true。最后,将bk[idx]设置为true表示当前字符串出现过。
如果l为3,根据字符串的后两个字符计算出一个索引idx,用于记录该字符串的出现情况。根据字符串的前三个字符计算出另外一个索引idx1,判断如果bk[idx]或者bk1[idx1]为true,说明之前已经出现过相同的字符串,将fl设置为true。最后,将bk1[idx1]设置为true表示当前字符串出现过。
在处理完所有的字符串后,根据fl的值输出相应的结果。如果fl为true,输出"YES";如果fl为false,输出"NO"。代码的主要目的是检查输入的字符串序列中是否存在满足特定条件的字符串。通过使用布尔数组bk和bk1来记录字符串的出现情况,然后根据不同的字符串长度进行相应判断,最终确定结果并输出。