HUSTOJ 1609 AntiVirus(AC自动机)

题目链接:http://acm.hust.edu.cn/problem.php?id=1609

题意:给出n个短串和一个长串,求长串中包含了多少个短串?

思路:首先将长串变短,因为每个字母连续出现的次数最多是n个串中该字母最长的次数。然后将n个串建立自动机。







const int MAX=1000005;

int C;

char s[MAX],s1[MAX*150],str[2005][200];







struct Node

{

	int next[26],pre,leaf,flag;



	void init()

	{

		memset(next,-1,sizeof(next));

		pre=-1;

		leaf=-1;

		flag=0;

	}

};







Node a[600005];

int e,root,n;

int Q;



void insert(char str[],int id)

{

	int p=root;

	for(int i=0;str[i];i++)

	{

		if(a[p].next[str[i]-'a']==-1) a[p].next[str[i]-'a']=++e;

		p=a[p].next[str[i]-'a'];

	}

	a[p].leaf=id;

}





void build_DFA()

{

	int i,p,q,k;

	queue<int> Q;

	Q.push(1);

	while(!Q.empty())

	{

		p=Q.front();

		Q.pop();

		for(i=0;i<26;i++) if(a[p].next[i]!=-1)

		{

			q=a[p].next[i];

			k=a[p].pre;

			while(k!=-1)

			{

				if(a[k].next[i]!=-1)

				{

					a[q].pre=a[k].next[i];

					break;

				}

				else k=a[k].pre;

			}

			Q.push(q);

		}

	}

}



int ans[2005];



void find(char str[])

{

	int p=root,i,pre,k;

	for(i=0;str[i];i++)

	{

		k=str[i]-'a';

		while(p>=1)

		{

			if(a[p].next[k]!=-1)

			{

				p=a[p].next[k];

				pre=p;

				while(pre>=1&&a[pre].flag==0)

				{

					a[pre].flag=1;

					if(a[pre].leaf!=-1) ans[a[pre].leaf]=1;

					pre=a[pre].pre;

				}

				break;

			}

			else p=a[p].pre;

		}

		if(p<1) p=1;

	}

}



void init()

{

	int i;

	for(i=0;i<=600000;i++) a[i].init();

	for(i=0;i<26;i++) a[0].next[i]=1;

	a[1].pre=0;

}



void deal()

{

    int L=0,i,j,k,t,len,p[26]={0};

    for(i=1;i<=n;i++)

    {

        len=strlen(str[i]);

        for(j=0;j<len;j++)

        {

            k=1;

            for(t=j+1;t<len&&str[i][t]==str[i][j];t++)

            {

                k++;

            }

            p[str[i][j]-'a']=max(p[str[i][j]-'a'],k);

            j=t-1;

        }

    }

    len=strlen(s);

    for(i=0;i<len;i++)

    {

        if(s[i]>='a'&&s[i]<='z') s1[L++]=s[i];

        else

        {

            k=0;

            for(j=i+1;s[j]>='0'&&s[j]<='9';j++)

            {

                k=k*10+s[j]-'0';

            }

            i=j+1;

            for(j=1;j<=p[s[i-1]-'a']+1&&j<=k;j++) s1[L++]=s[i-1];

        }

    }

    s1[L]=0;

}



int main()

{

    for(scanf("%d",&C);C--;)

    {

        scanf("%d",&n);

        int i;

        init();

        root=e=1;

        for(i=1;i<=n;i++) scanf("%s",str[i]),insert(str[i],i);

        scanf("%s",s);

        deal();

        build_DFA();

        memset(ans,0,sizeof(ans));

        find(s1);

        int A=0;

        for(i=1;i<=n;i++) if(ans[i]) A++;

        if(A) printf("Yes");

        else printf("No");

        printf(" %d\n",A);

    }

    return 0;

}

  

你可能感兴趣的:(AC自动机)