ZOJ 3535 Gao the String II

搞了半天,预处理各种错。。。

先说下题目意思吧,不好理解,当时比赛的时候是以为把得到的S和每个Bi去比,Bi的每一位如果正确对上了就算得1分,结果样例直接没过,就扔掉了

后来看了解题报告和标程,发现应该是S和每个Bi去比,当Bi是S的子串时才得1分


那么我们可以用自动机来进行DP,首先预处理对于每个Ai,可以和Aj的第几位开始的后缀进行link,然后剩下的自动机DP就比较简单了

定义dp[i][j][k]表示当前长度为i,且在自动机的状态j,并且这个状态是由link Ak转移过来的,我们对于Ak的每个可行的link单词进行枚举,转移即可


代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int MAX=10000;
struct node 
{
	int next[26],fail,s;
};
node trie[MAX];
int idx,n,m,L,len[55];
char a[55][15];
vectoradj[55],start[55];
int dp[55][555][55];
int New()
{
	for(int i=0;i<26;i++)
		trie[idx].next[i]=-1;
	trie[idx].s=0;
	return idx++;
}
void insert(char str[])
{
	int p=0,i=0,del;
	while(str[i])
	{
		del=str[i]-'a';
		if(trie[p].next[del]==-1)
			trie[p].next[del]=New();
		p=trie[p].next[del];
		i++;
	}
	trie[p].s++;
}
void build_fail()
{
	queueque;
	int fa,pre,i;
	trie[0].fail=-1;
	for(i=0;i<26;i++)
	{
		if(trie[0].next[i]!=-1)
		{
			trie[trie[0].next[i]].fail=0;
			que.push(trie[0].next[i]);
		}
		else
			trie[0].next[i]=0;
	}
	while(!que.empty())
	{
		fa=que.front();
		que.pop();
		trie[fa].s+=trie[trie[fa].fail].s;
		for(i=0;i<26;i++)
		{
			pre=trie[fa].fail;
			while(trie[pre].next[i]==-1)
				pre=trie[pre].fail;
			if(trie[fa].next[i]!=-1)
			{
				trie[trie[fa].next[i]].fail=trie[pre].next[i];
				que.push(trie[fa].next[i]);
			}
			else	
				trie[fa].next[i]=trie[pre].next[i];
		}
	}
}
void init()
{
	int i,j,k,l;
	for(i=0;i<=n;i++)
	{
		adj[i].clear();
		start[i].clear();
	}
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
		{
			for(k=0;kL)
						continue;
					int ns=i;
					int x=start[j][k],sum=0;
					for(int y=0;y+x"<


你可能感兴趣的:(字符串)