题意:
题目给出两个操作,1是插入字符串,2是询问这个字符串是否是之前插入的字符串前后缀的组合或者这个字符串本身就是之前插入的字符串的前缀或后缀。
题解:
直接字典树搞,弄两个字典树,一个存前缀,一个存后缀,然后查询时去两个字典树中查找,如果两个搜到的两个位置相加>=len,那么是可行的。
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
#include<ctype.h>
#define B(x) (1<<(x))
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int maxn=50005;
const int maxm=105;
const int SIZE=1000005;
struct TRIE{
int next[SIZE][26];
int cnt,root;
int newNode(){
for(int i=0;i<26;i++)
next[cnt][i]=-1;
cnt++;
return cnt-1;
}
void Init(){
cnt=0;
root=newNode();
}
void Insert(char buff[]){
int now=root;
for(int i=0;buff[i];i++){
int k=buff[i]-'a';
if(next[now][k]==-1)
next[now][k]=newNode();
now=next[now][k];
}
}
int Search(char buff[]){
int now=root;
int i;
for(i=0;buff[i];i++){
int k=buff[i]-'a';
if(next[now][k]==-1)
return i;
now=next[now][k];
}
return i;
}
}trie1,trie2;
void up_down(char T[],char S[],int len){
for(int i=0;i<len;i++)
T[i]=S[len-i-1];
T[len]='\0';
}
char str[maxn],s[maxn];
int main(){
//freopen("E:\\read.txt","r",stdin);
int n,op,len,pos1,pos2;
while(scanf("%d",&n)!=EOF){
trie1.Init();
trie2.Init();
while(n--){
scanf("%d%s",&op,str);
if(op==1){
trie1.Insert(str);
len=strlen(str);
up_down(s,str,len);
trie2.Insert(s);
}else if(op==2){
pos1=trie1.Search(str);
len=strlen(str);
up_down(s,str,len);
pos2=trie2.Search(s);
if(pos1+pos2>=len)
puts("YES");
else
puts("NO");
}
}
}
return 0;
}
/**
8
1 abc
2 abcabc
1 qwer
2 ar
2 qwer
2 abcqwer
2 qb
2 we
3
1 abc
2 abab
2 abba
11
1 aaac
1 bbbc
1 aabbb
2 aaaabbb
2 aaaaabbbb
2 aaac
2 bbbc
2 aabbb
2 caaa
2 cbbb
2 bbbaa
*/