【SHTSC2013】阶乘字符串

206 篇文章 0 订阅
119 篇文章 0 订阅

Description
给定一个由前n个小写字母组成的串S。

串S是阶乘字符串当且仅当前n个小写字母的全排列(共n!种)都作为S的子序列(可以不连续)出现。

由这个定义出发,可以得到一个简单的枚举法去验证,但是它实在太慢了。所以现在请你设计一个算法,在1秒内判断出给定的串是否是阶乘字符串。

Input
输入第1行一个整数T,表示这个文件中会有T组数据。

接下来分T个块,每块2行:

第1行一个正整数n,表示S由前n个小写字母组成。

第2行一个字符串S。

Output
对于每组数据,分别输出一行。每行是YES或者NO,表示该数据对应的串S是否是阶乘字符串。

Sample Input
2

2

bbaa

2

aba

Sample Output
NO

YES

Data Constraint
在这里插入图片描述

Hint
样例解释:

第一组数据中,ab这个串没有作为子序列出现。

.
.
.
.
.
分析
首先,当n>21时是无解的,也就是输出“NO”

证明:无(哪位大佬发一下啊)

ans[S]表示当前的集合为S时满足阶乘字符串时的最后一个字母的位置。
g[i][j]表示以i+1开始的第一个j字母出现的位置。
然后枚举子集转移,最后判断一下是否满足f[(1<<n)−1]≤l

.
.
.
.
.
程序:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int f[22],ans[3000000],g[451][27]; 
char s[451];

int main()
{
	f[0]=1;
	for (int i=1;i<=22;i++) 
		f[i]=f[i-1]*2;
	int t;
	scanf("%d",&t);
	while (t--)
	{
		int n;
		scanf("%d",&n);
		if (n>21)
		{ 
			printf("NO\n");
			scanf("%*s");
			continue;
		}
		cin>>s+1;
		int l=strlen(s+1);
		
		for (int i=0;i<=n-1;i++) 
			g[l][i]=g[l+1][i]=l+1;
			
		for (int i=l;i>=1;i--)
		{
			for (int j=0;j<=n-1;j++)
				g[i-1][j]=g[i][j];
			g[i-1][s[i]-'a']=i;
		}
		
		for (int i=1;i<=f[n]-1;i++)
		{
			ans[i]=0;
			for (int k=0;f[k]<=i;k++) 
				if (i&f[k]) ans[i]=max(ans[i],g[ans[i^f[k]]][k]);
		}
		
		if (ans[f[n]-1]<=l) cout<<"YES"<<endl; else cout<<"NO"<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值