[Luogu 3966] TJOI 2013 单词

<题目链接>

经典ACAM。


注意单词之间添加字符,以及对重复单词的处理。

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN=210,MAXM=1000010,MAXL=1000010;
char str[MAXL],p[MAXN+MAXL];
int n;
class ACAM
{
	public:
		ACAM(void)
		{
			cnt=0;
			memset(mp,0,sizeof mp);
			memset(ans,0,sizeof ans);
			memset(s,0,sizeof s);
		}
		void Insert(char *str,int k)
		{
			int x=0;
			for(int i=0,t;str[i];++i)
			{
				if(!s[x].c[t=num(str[i])])
					s[x].c[t]=++cnt;
				x=s[x].c[t];
			}
			if(!s[x].index)
				s[x].index=k;
			mp[k]=s[x].index;
		}
		void GetFail(void)
		{
			queue<int> q;
			for(int i=0,t;i<26;++i)
				if(t=s[0].c[i])
					q.push(t);
			while(!q.empty())
			{
				int x=q.front();
				q.pop();
				for(int i=0,t,f;i<26;++i)
					if(t=s[x].c[i])
					{
						f=s[t].fail=s[s[x].fail].c[i];
						s[t].lst=s[f].index?f:s[f].lst;
						q.push(t);
					}
					else
						s[x].c[i]=s[s[x].fail].c[i];
			}
		}
		void Search(char *p)
		{
			int x=0;
			for(int i=0;p[i];++i)
			{
				if(p[i]==' ')
				{
					x=0;
					continue;
				}
				if(s[x=s[x].c[num(p[i])]].index)
					++ans[s[x].index];
				for(int j=s[x].lst;j;j=s[j].lst)
					++ans[s[j].index];
			}
			for(int i=1;i<=n;++i)
				printf("%d\n",ans[mp[i]]);
		}
	private:
		int cnt,mp[MAXN],ans[MAXN];
		struct node
		{
			int index,fail,lst,c[26];
		}s[MAXM];
		int num(char c)
		{
			return c-'a';
		}
}AC;
int main(int argc,char *argv[])
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		scanf("%s",str);
		AC.Insert(str,i);
		strcat(p,str);
		strcat(p," ");
	}
	AC.GetFail();
	AC.Search(p);
	return 0;
}

谢谢阅读。

posted @ 2017-12-22 11:14  Capella  阅读(189)  评论(2编辑  收藏  举报

谢谢光临