zoukankan      html  css  js  c++  java
  • 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);
    	for(int i=1;i<=m;++i)
    	{
    		if(t[i]=='-')
    		{
    			--len;
    			if(len<0)
    				len=0;
    			printf("%d
    ",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-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
    ",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
    ",d[f[len]]);
    	}
    //  fclose(stdin);
    //  fclose(stdout);
        return 0;
    }
    
    静渊以有谋,疏通而知事。
  • 相关阅读:
    三元表达式 列表和字典推导式 函数对象 名称空间 作用域 global和nonlocal 函数装饰器 枚举对象
    函数参数 打散机制 字符串比较 返回值
    函数简介
    三种字符串的介绍 文件的读写
    字符编码
    数据类型及其常用方法 数据类型转换 可变与不可变 值拷贝与深浅拷贝
    流程控制 while和for循环
    变量命名规范 常量 输入和输出 注释 数据类型 运算符 逻辑运算符
    语言分类 编译型和解释型语言分析 环境变量 代码执行的方式 pip介绍 变量
    Python django tests
  • 原文地址:https://www.cnblogs.com/autoint/p/9835871.html
Copyright © 2011-2022 走看看