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< 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<

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\n",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>1;
				if(i/(mid*x)>k)l=mid+1;
				else r=mid;
			}
			if(i/(l*x)==k)putchar('1');
			else putchar('0');
		}
	}
	return 0;
}

你可能感兴趣的:(BUAA Summer Practice 2017 #1 字符串专场)