HDU-2896 病毒侵袭 && HDU-3065 病毒侵袭持续中(AC自动机)

HDU-2896

注意数组范围。

#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;
}

HDU-3065

和上面的题类似,然而我却一直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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值