zoukankan      html  css  js  c++  java
  • BUAA Summer Practice 2017 #1 字符串专场

    https://vjudge.net/contest/262753#overview

    C - Regular Number HDU - 5972

    bitset temp, temp[i]=1表示 此前i个位置都能完全匹配,&=bt[x-'0']来递推

    int n,a[1111][12];
    char s[5000050];
    int main()
    {
    	while(~scanf("%d",&n))
    	{
    		bitset<1000> bt[11];
    		re(i,0,9)bt[i].reset();
    		re(i,1,n)
    		{
    			int x;inin(x);
    			re(j,1,x)
    			{
    				int y;inin(y);
    				bt[y][i-1]=1;
    			}
    		}
    		strin(s+1);
    		int len=strlen(s+1);
    		while(s[len]<'0'||s[len]>'9')len--;
    		bitset<1000> temp;
    		temp.reset();
    		re(i,1,len)
    		{
    			temp<<=1;
    			temp[0]=1;
    			temp&=bt[s[i]-'0'];
    			if(temp[n-1]==1)
    			{
    				fwrite(s+i-n+1,sizeof(s[0]),n,stdout);
    				puts("");
    			}
    		}
    	}
    	return 0;
    }
    

    A - Password Suspects UVALive - 4126

    AC自动机上DP,ans[x][y][s]表示当前在x结点,已经用了y个字符,已经含有了s集合中的子串,之后还有多少种方法。

    调了半天发现没考虑输入相同的子串。

    
    int ch[111][27],pre[111],tag[111],ed;
    int n,m;
    void add(char *s,int x)
    {
    	int temp=0;
    	while(*s)
    	{
    		int c=(*s)-'a';
    		if(!ch[temp][c])ch[temp][c]=++ed;
    		temp=ch[temp][c];
    		s++;
    	}
    	tag[temp]|=(1<<x);
    }
    queue<int> h;
    void getpre()
    {
    	re(i,0,25)if(ch[0][i])h.push(ch[0][i]);
    	while(!h.empty())
    	{
    		int x=h.front();h.pop();
    		tag[x]|=tag[pre[x]];
    		re(i,0,25)
    		{
    			if(!ch[x][i])
    			{
    				ch[x][i]=ch[pre[x]][i];
    				continue;
    			}
    			int vv=ch[x][i];
    			int k=pre[x];
    			pre[vv]=ch[k][i];
    			h.push(vv);
    		}
    	}
    }
    bool bo[105][28][1028];
    LL ans[105][28][1028];
    LL dfs(int x,int y,int s)
    {
    	if(bo[x][y][s])return ans[x][y][s];
    	bo[x][y][s]=1;
    	if(y==n)return ans[x][y][s]=(s==(1<<m)-1)?1:0;
    	LL &aa=ans[x][y][s];
    	aa=0;
    	re(i,0,25)aa+=dfs(ch[x][i],y+1,s|tag[ch[x][i]]);
    	return aa;
    }
    char ss[332];
    void out(int x,int y,int s)
    {
    	if(y==n)
    	{
    		if(s==(1<<m)-1)ss[n]=0,puts(ss);
    		return ;
    	}
    	re(i,0,25)
    	{
    		int vv=ch[x][i];
    		if(bo[vv][y+1][s|tag[vv]]&&ans[vv][y+1][s|tag[vv]])
    			ss[y]=i+'a',out(vv,y+1,s|tag[vv]);
    	}	
    }
    int tt;
    char s[122];
    int main()
    {
    //	freopen("a.in","r",stdin);
    	while(~scanf("%d%d",&n,&m))
    	{
    		tt++;
    		if(!n)return 0;
    		ed=0;
    		Clear(pre,0);
    		Clear(ans,0);
    		Clear(bo,0);
    		Clear(ch,0);
    		Clear(tag,0);
    		re(i,1,m)strin(s+1),add(s+1,i-1);
    		getpre();
    		LL ans=dfs(0,0,0);
    		printf("Case %d: %lld suspects
    ",tt,ans);
    		if(ans<=42)out(0,0,0);
    	}
    	return 0;
    }
    

    L - The Problem to Slow Down You UVALive - 7041

    求两个字符串相同回文子串数目

    构建回文树然后dfs相同结点(路径)

    struct st
    {
    	int ch[200010][27],sum[200010],len[200010],pre[200020],ed;
    	char s[200010];
    	int getpre(int x,int y)
    	{
    		while(s[y]!=s[y-len[x]-1])x=pre[x];
    		return x;
    	}
    	void Main()
    	{
    		ed=1;
    		Clear(ch[0],0),Clear(ch[1],0);
    		len[0]=0,len[1]=-1;
    		pre[0]=1;
    		strin(s+1);
    		int l=strlen(s+1),temp=0;
    		s[0]=-1;
    		re(i,1,l)
    		{
    			int now=getpre(temp,i);
    			if(!ch[now][s[i]-'a'])
    			{
    				int k=++ed;
    				sum[k]=0;
    				Clear(ch[k],0);
    				len[k]=len[now]+2;
    				pre[k]=ch[getpre(pre[now],i)][s[i]-'a'];
    				ch[now][s[i]-'a']=k;
    			}
    			sum[temp=ch[now][s[i]-'a']]++;
    		}
    		rre(i,ed,0)sum[pre[i]]+=sum[i];
    	}
    }t[2];
    LL ans;
    void dfs(int t0,int t1)
    {
    	if(t[0].len[t0]>0)ans+=1LL*t[0].sum[t0]*t[1].sum[t1];
    	re(i,0,25)if(t[0].ch[t0][i]&&t[1].ch[t1][i])dfs(t[0].ch[t0][i],t[1].ch[t1][i]);
    }
    int T;
    int main()
    {
    	inin(T);int tt=T;
    	while(T--)
    	{
    		ans=0;
    		t[0].Main();
    		t[1].Main();
    		dfs(0,0);
    		dfs(1,1);
    		printf("Case #%d: %lld
    ",tt-T,ans);
    	}
    	return 0;
    }
    
    

    K - Om Nom and Necklace CodeForces - 526D

    可以证明i-pre[i]是最短的循环节长度(B+A),然后判断是否能把i拆成k个循环节+一个长度小于循环节的串,或者直接拆成k+1个循环节,前者用二分判,后者直接判整除。

    char a[1000010];
    int pre[1000010];
    void getpre(char *s)
    {
        int k=0;int n=strlen(s+1);
        re(i,2,n)
        {
            while(k&&s[i]!=s[k+1])k=pre[k];
            if(s[i]==s[k+1])k++;
            pre[i]=k;
        }
    }
    int n,k;
    int main()
    {
    	inin(n),inin(k);
    	strin(a+1);
    	getpre(a);
    	int len=strlen(a+1);
    	re(i,1,len)
    	{
    		int x=i-pre[i];
    		if(i%x==0&&(i/x)%(k+1)==0)putchar('1');
    		else 
    		{
    			int l=1,r=i/x,mid;
    			while(l<r)
    			{
    				mid=(l+r)>>1;
    				if(i/(mid*x)>k)l=mid+1;
    				else r=mid;
    			}
    			if(i/(l*x)==k)putchar('1');
    			else putchar('0');
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    [LC] 131. Palindrome Partitioning
    [LC] 216. Combination Sum III
    [LC] 90. Subsets II
    [Algo] 73. Combinations Of Coins
    [Algo] 66. All Valid Permutations Of Parentheses I
    Hive 和 HBase区别
    form表单 多种提交方式 [转]
    HDFS 好的文章链接
    js 获取字符串的 像素 宽度 ----字符串格式化输出
    python 本地变量和全局变量 locals() globals() global nonlocal 闭包 以及和 scala 闭包的区别
  • 原文地址:https://www.cnblogs.com/HugeGun/p/10627229.html
Copyright © 2011-2022 走看看