描述
问一堆单词中,哪些是 palinword
并输出。
palinword
的定义为,包含两个不同的回文子串,并且要求回文子串不能互相包含,可以部分重叠。
规模
单个单词长度 l<=255。
样例输入
MOEILIJKHEDEN INVOER VERNEDEREN AMUMA AMAMA MUMMUM AMATRAMA AAAA ABATRABAR DUMMY WORDS
样例输出
MOEILIJKHEDEN VERNEDEREN AMAMA MUMMUM
分析
说实话这题有点类似脑筋急转弯,,, 回文串有两种,一种是奇回文,形式为 SXS。一种是偶回文,形式为 SS。
既然题目说不能互相包含,那么我们只考虑两种基本回文串,长度为 3 的奇回文,长度为 4 的偶回文。因为这些基本回文串一定分属于两个不同的大回文串。然后用 Hash 判重复即可。
不过有唯一的特例,aaaa
包含了 aaa
,这很好解决。对于位置 i,其上的字符为 X,先匹配长度为 3 的奇回文,如果匹配成功,那一定是 SXS 的形式,紧接着,如果长度为 4 的偶回文匹配成功,那一定是 SXSY 的形式,因为是偶回文,所以四个字母都必须相等,显然不满足。故匹配成功直接 continue 即可。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn = 260, hashBase = 1007;
char s[maxn];
set<ull> palindromes;
inline bool isPalinword(const char *str)
{
int len = strlen(s);
palindromes.clear();
for(int i = 1; i < len-1; i++)
{
ull hashNum = s[i-1]*hashBase*hashBase + s[i]*hashBase + s[i+1];
if(s[i-1] == s[i+1])
{
palindromes.insert(hashNum);
if(palindromes.size() >= 2) return true;
continue;
}
if(i == len-2) continue;
if(s[i] == s[i+1] && s[i-1] == s[i+2])
{
hashNum = hashNum * hashBase + s[i+2];
palindromes.insert(hashNum);
if(palindromes.size() >= 2) return true;
}
}
return false;
}
int main()
{
while(~scanf("%s", s))
{
if(isPalinword(s))
printf("%s\n", s);
}
return 0;
}