注意数组范围。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int N = 3000005;
const int Letters = 95;//不能开大了,不然会MLE
/*
注意这些细节127-32 = 95,我竟然因为开到了135而爆了内存,
长个教训,以后先估值
*/
char str[10005], keyword[205];
int flag[505];
int head, tail;
struct Trie
{
Trie *fail;
Trie *next[Letters];
int count;
Trie() //init
{
fail = NULL;
count = 0;
memset(next,0,sizeof(next));
//for(int i = 0; i < Letters; ++i)
//next[i] = NULL;
}
}*q[N];
Trie *root;
void Insert(char *str,int num) //??Trie
{
int temp, len;
Trie *p = root;
len = strlen(str);
for(int i = 0; i < len; ++i)
{
temp = str[i] - 32;
if(p->next[temp] == NULL)
p->next[temp] = new Trie();
p = p->next[temp];
}
p->count = num;
}
void Build_ac() //???fail???BFS
{
root->fail = NULL;
q[tail++] = root;
Trie *p,*temp;
while(head != tail)
{
p = q[head++]; //????
temp = NULL;
for(int i = 0; i < Letters; ++i)
{
if(p->next[i] != NULL)
{
if(p == root) //?????fail????
p->next[i]->fail = root;
else
{
temp = p->fail; //????
while(temp != NULL) //2??????????or????
{
if(temp->next[i] != NULL) //????
{
p->next[i]->fail = temp->next[i];
break;
}
temp = temp->fail;
}
if(temp == NULL) //???????
p->next[i]->fail = root;
}
q[tail++] = p->next[i]; //??
}
}
}
}
int Query() //??
{
int index, len, result = 0;
Trie *p = root; //Tire??
len = strlen(str);
for(int i = 0; i < len; ++i)
{
index = str[i] - 32;
while(p->next[index] == NULL && p != root) //??????
p = p->fail;
p = p->next[index];
if(p == NULL)
p = root;
Trie *temp = p; //p???temp?????
while(temp != root )
{
flag[temp->count] = 1;
if(temp->count != 0)
result++;
temp = temp->fail;
}
}
return result;
}
int main()
{
int n,m;
while(~scanf("%d",&n))
{
head = tail = 0;
root = new Trie();
getchar();
for(int i = 1; i <= n; ++i)
{
gets(keyword);
Insert(keyword,i);
}
Build_ac();
scanf("%d",&m);
int sum = 0;//??
for(int i = 1;i <= m;i++)
{
memset(flag,0,sizeof(flag));
scanf("%s", str);
if(Query())
{
printf("web %d:",i);
sum++;
for(int j = 1;j <= n;j++)
if(flag[j])
printf(" %d",j);
printf("\n");
}
}
printf("total: %d\n",sum);
}
return 0;
}
和上面的题类似,然而我却一直wa,最后胡改才ac了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 500005;
const int Letters = 26;
char s[1005][55],str[2000015];
int flag[1005];
inline int idx(char c){return c-'A';}
struct Trie
{
int count;
Trie *fail;
Trie *next[Letters];
Trie()
{
count = 0;
fail = NULL;
memset(next,0,sizeof(next));
}
}*q[N];
int head,tail;
Trie *root;
void Insert(char *word, int num)
{
Trie *p = root;
int i = 0, index;
while(word[i])
{
index = idx(word[i]);
if(p->next[index] == NULL)
p->next[index] = new Trie();
p = p->next[index];
i++;
}
p->count = num;
}
void Build_ac()
{
int i;
root->fail = NULL;
q[tail++] = root;
while(head != tail)
{
Trie *temp = q[head++];
Trie *p = NULL;
for(int i = 0; i < Letters; i++)
{
if(temp->next[i])
{
if(temp == root)
temp->next[i]->fail = root;
else
{
p = temp->fail;
while(p != NULL)
{
if(p->next[i] != NULL)
{
temp->next[i]->fail = p->next[i];
break;
}
p = p->fail;
}
if(p == NULL)
temp->next[i]->fail = root;
}
q[tail++] = temp->next[i];
}
}
}
}
void Query()
{
int i = 0, index;
Trie *p = root;
while(str[i])
{
if(str[i] < 'A' || str[i] > 'Z')
{
p = root;
i++;
continue;
}
index = str[i] - 'A';
while(p->next[index] == NULL && p != root)
p = p->fail;
p = p->next[index];
p = (p==NULL)?root:p;
Trie *temp = p;
while(temp != root && temp->count != 0)
{
flag[temp->count] ++;
temp = temp->fail;
}
i++;
}
}
int main()
{
int n;
while(~scanf("%d", &n))
{
head = tail = 0;
root = new Trie();
getchar();
for(int i = 1; i <= n; i++)
{
gets(s[i]);
flag[i] = 0;
Insert(s[i],i);
}
Build_ac();
gets(str);
Query();
for(int i = 1; i <= n; i++)
{
if(flag[i])
{
printf("%s: %d\n", s[i],flag[i]);
}
}
}
return 0;
}