建立两个字典树,一个按照前缀储存,一个按照后缀储存。
查找时就把要查找的字符串的正串和反串分别放到两个树里跑``,用两个数组记录到哪里可以找到对应的前缀(f)与后缀(e),然后扫一遍即可。
#include <iostream>
#include <algorithm>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <queue>
#include <map>
#define N 500000
using namespace std;
const int INF = 0x3f3f3f3f;
struct Node{
Node* ch[26];
bool flag;
};
bool f[30],e[30];
char s1[30],s2[30];
char s[N][30];
struct Tree{
Node a[N];
int p;
Node* root;
Node* newNode(){
p++;
memset(a[p].ch,0,sizeof(a[p].ch));
a[p].flag = 0;
return &a[p];
}
Tree(){
p = 0;
root = newNode();
}
void insert(char s[]){
Node* cur = root;
while (*s != '\0')
{
int x = *s - 'a';
if(cur->ch[x] == NULL){
cur->ch[x] = newNode();
}
cur = cur->ch[x];
s++;
}
cur->flag = 1;
}
void check(char s[],bool t[]){
Node* cur= root;
int cnt = -1;
while (*s != '\0')
{
if(cur->flag){
t[cnt] = 1;
}
int x = *s - 'a';
if(cur->ch[x] == NULL){
return;
}
cnt++;
cur = cur->ch[x];
s++;
}
}
};
Tree zheng,fan;
void turn(){
int len = strlen(s1);
for(int i=0;i<len;i++){
s2[i] = s1[len-1-i];
}
s2[len] = '\0';
}
bool check(){
memset(f,0,sizeof(f));
memset(e,0,sizeof(e));
zheng.check(s1,f);
fan.check(s2,e);
int len = strlen(s1);
for(int i=0;i < len-1;i++){
if(f[i] && e[len-2-i]){
return 1;
}
}
return 0;
}
int main(){
int i = -1;
while (gets(s1) && s1[0] != '\0')
{
i++;
zheng.insert(s1);
turn();
fan.insert(s2);
strcpy(s[i],s1);
}
for(int j=0;j<=i;j++){
strcpy(s1,s[j]);
turn();
if(check()){
printf("%s\n",s1);
}
}
return 0;
}