题目:给你一个目标串,和一些模式串,问每个模式串是否在目标串中出现。
分析:字符串,AC自动机。一开始用KMP算法,TLE了才发现会超时,改用AC自动机;
直接利用AC自动机存储,查询即可,然后按顺序输出;
如果模式串中有重复的,直接利用并查集合并即可,只须判断父节点。
说明:╮(╯▽╰)╭计算复杂度时,数据组数被忽略了;注意初始化。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
char s[100002],t[1002];
#define nodesize 40004 //节点个数
#define dictsize 52 //字符集大小
typedef struct node1
{
int flag; //值域
node1* fail;
node1* next[dictsize];
}tnode;
tnode dict[nodesize+1];
tnode* Q[nodesize+1];
int ID[256];
int visit[1002];
int father[1002];
class AC_DFA
{
private:
int size;
tnode* root;
public:
AC_DFA() {makeID();init();}
void makeID() {
for ( int i = 0 ; i < 26 ; ++ i ) {
ID['a'+i] = i;
ID['A'+i] = i+26;
}
}
void init() {
memset( dict, 0, sizeof( dict ) );
root=NULL; size=0; root=newnode();
for ( int i = 0 ; i < 1001 ; ++ i )
father[i] = i;
}
tnode* newnode() {
dict[size].fail = root;
return &dict[size ++];
}
void insert( char* word, int id ) {
tnode* now = root;
for ( int i = 0 ; word[i] ; ++ i ) {
if ( !now->next[ID[word[i]]] )
now->next[ID[word[i]]] = newnode();
now = now->next[ID[word[i]]];
}
if ( now->flag ) father[id] = now->flag;
else now->flag = id;
}
void setfail() {
Q[0] = root; root->fail = NULL;
for ( int move = 0,save = 1 ; move < save ; ++ move ) {
tnode* now = Q[move];
for ( int i = 0 ; i < dictsize ; ++ i )
if ( now->next[i] ) {
tnode* p = now->fail;
while ( p && !p->next[i] ) p = p->fail;
now->next[i]->fail = p?p->next[i]:root;
Q[save ++] = now->next[i];
}
}
}
void query( char* line, int q ) {
memset( visit, 0, sizeof( visit ) );
tnode* now = root;
for ( int i = 0 ; line[i] ; ++ i ) {
while ( now && !now->next[ID[line[i]]] ) now = now->fail;
now = now?now->next[ID[line[i]]]:root;
for ( tnode* p = now ; p ; p = p->fail )
visit[p->flag] = 1;
}
for ( int i = 1 ; i <= q ; ++ i )
if ( visit[father[i]] )
printf("y\n");
else printf("n\n");
return;
}
}dfa;
/* AC_DFA end */
int main()
{
int k,q;
scanf("%d",&k);
while ( k -- ) {
dfa.init();
scanf("%s%d",s,&q);
for ( int i = 1 ; i <= q ; ++ i ) {
scanf("%s",t);
dfa.insert( t, i );
}
dfa.setfail();
dfa.query(s, q);
}
return 0;
}