test20181020 B君的第二题

B君的第二题

1
2

分析

题目就是让你求文本框与s匹配到了哪个位置。

考场70分

一看就是裸的kmp,直接打上去。

const int MAXN=1e5+8;
char s[MAXN],t[MAXN];
int n,m;
int nx[MAXN];
int f[MAXN],len;

int main()
{
  freopen("xining.in","r",stdin);
  freopen("xining.out","w",stdout);
	scanf("%s",s+1);
	n=strlen(s+1);
	scanf("%s",t+1);
	m=strlen(t+1);
	
	for(int i=2;i<=n;++i)
	{
		int p=nx[i-1];
		while(p&&s[p+1]!=s[i])
			p=nx[p];
		if(s[p+1]==s[i])
			++p;
		nx[i]=p;
	}
	
	printf("%d\n",n);
	for(int i=1;i<=m;++i)
	{
		if(t[i]=='-')
		{
			--len;
			if(len<0)
				len=0;
			printf("%d\n",n-f[len]);
			continue;
		}
//		cerr<<"pro "<<i<<endl;
		int p=f[len];
//		cerr<<" p="<<p<<endl;
		while(p&&s[p+1]!=t[i])
			p=nx[p];
		if(s[p+1]==t[i])
			++p;
		f[++len]=p;
//		cerr<<" p="<<p<<endl;
		printf("%d\n",n-p);
	}
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

结果TLE了。实际上时间复杂度\(O(n^2)\)

标解

这道题能卡kmp,是因为往回走后重新匹配跳next时复杂度没了保证。

退格操作可以让匹配长度剧增,这与kmp要满足长度增加量最多为文本串的长度的性质不符,所以要被卡。

B君:可以前n/2都是a,然后后面一个-一个b交替出现,就可以把kmp卡成n方的了。

但是AC自动机中的一个构建优化是把不存在的儿子补齐,所以考虑AC自动机。

然后因为AC自动机是在Trie图上建的,距离不能直接求,所以要预处理。

时间复杂度\(O(n)\)

const int MAXN=1e5+7;

vector<int>a[MAXN];
int d[MAXN];

const int CHARSET=26;
struct Trie
{
	int sz;
	int to[MAXN][CHARSET];
	int nx[MAXN];
	int fa[MAXN];
	int v[MAXN];
	
	il void ins(rg char*s)
	{
		rg int p=0;
		for(;*s;++s)
		{
			rg int c=*s-'a';
			if(to[p][c]==0)
			{
				to[p][c]=++sz;
				fa[sz]=p;
			}
			p=to[p][c];
		}
		v[p]=1;
	}
	
	il void build()
	{
		rg queue<int>Q;
		Q.push(0);
		while(!Q.empty())
		{
			rg int x=Q.front();
			Q.pop();
			v[x]|=v[nx[x]];
			for(rg int i=0;i<CHARSET;++i)
			{
				if(to[x][i])
				{
					nx[to[x][i]]=x?to[nx[x]][i]:0;
					Q.push(to[x][i]);
				}
				else
				{
					to[x][i]=x?to[nx[x]][i]:0;
				}
			}
		}
		for(rg int i=0;i<=sz;++i)
			for(rg int j=0;j<CHARSET;++j)
			{
				a[to[i][j]].push_back(i);
			}
		memset(d,0x3f,sizeof d);
		for(rg int i=0;i<=sz;++i)
			if(v[i])
			{
				Q.push(i);
				d[i]=0;
			}
		while(!Q.empty())
		{
			rg int x=Q.front();
			Q.pop();
			for(rg int i=0;i<a[x].size();++i)
			{
				rg int y=a[x][i];
				if(d[y]>d[x]+1)
				{
					d[y]=d[x]+1;
					Q.push(y);
				}
			}
		}
	}
}T;

char s[MAXN],t[MAXN];

int f[MAXN],len;

int main()
{
  freopen("xining.in","r",stdin);
  freopen("xining.out","w",stdout);
	scanf("%s",s);
	T.ins(s);
	T.build();
	scanf("%s",t);
	printf("%d\n",d[f[len]]);
	for(rg int i=0;t[i];++i)
	{
		if(t[i]=='-')
		{
			if(len>0)
				--len;
		}
		else
		{
			rg int x=T.to[f[len]][t[i]-'a']; // edit 1
			f[++len]=x;
		}
//		cerr<<"f="<<f[len]<<endl;
		printf("%d\n",d[f[len]]);
	}
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

posted on 2018-10-23 11:59  autoint  阅读(192)  评论(0编辑  收藏  举报

导航