您的位置:首页 > 其它

【未出现的字串】解题报告

2011-10-28 20:01 169 查看


题目描述

[说明]此题中的子数字串,数字并不一定连续出现在母数字串中.比如我们定义1 3 是串1 5 3

的一个子串,但3 5 不是1 5 3 的一个子串.

串1 5 3 的所有子串为:

1

5

3

1 5

5 3

1 3

1 5 3

共7 个.

[题目描述]有一个长度为n 的数字串,其中会出现数字1,2,3,...,q(5<=q<=9).SubRaY 遇到的问

题是,需要求出一个长度最小的串(出现的数字也是1..q),使得该串不是这个数字串的子串.为

了简化问题,你只需要输出这个串的长度即可.

例如对于数字串S=

1 3 5 2 4 1 3 5 2 2 2 2 3 4 1 5 3 2(q=5)

长度为1 和2 的数字子串全出现过,但是你找不出子串S'=4 4 4.因此答案是3

[数据范围]

对于30%的数据,1<=n<=20,q=5

对于100%的数据,1<=n<=100000,5<=q<=9


输入格式

第一行两个数,串长n 和出现的数字的个数q

接下来n 行表示该数字串每一位的数字.


输出格式

未出现的子串的最小长度

这道题动规方法很麻烦。题解中有用纯数学方法的。

这道题利用集合的概念能够用O(n)的复杂度解出来。

设把串分为k段,每一段都包含1~q,如果能找到k段,

则说明,有字串(1111...)k个。(2222...)k个。。。(qqqq...)k个

(1234...q),(1234..q-1)这些子串都有了,则(1234...q)的子串也都有了

所以容易知道,最段的未出现的串长度是k+1

这个方法可以利用位集合来处理,这是一个好东西呀!

它用每一位来存储一个状态。

因此他可以有两个作用:

1、可以用作hash表,比使用bool类型节约空间得多!!

2、因为每一位对应一个值,所以可以作为没有重复元素的集合来使用!!

这是个好东西呀!!

bitset的基本操作:

1、reset,清零操作。也可写成=0

2、set(i),把某一位设为1

3、reset(i),把每一位设为0

4、==,支持等于比较

#include <cstdio>
#include <bitset>
using std::bitset;
long n;long p;
long num[100002];

int main()
{
bitset<100002> unit;
bitset<100002> s;

scanf("%ld%ld",&n,&p);
for (long i=1;i<p+1;i++)
s.set(i);
long ans = 1;
for (long i=1;i<n+1;i++)
{
long num;
scanf("%ld",&num);
unit.set(num);
if (unit==s)
{
ans ++;
unit=0;
continue;
}
}
printf("%ld",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  存储