HDU 2668 Daydream(最长不重复子序列)

题目描述:
Daydream
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u

Description
Welcome to 2009 HDU Girl’s Cup, bless you will happy in it.
Every girl are beautiful if you use you heart to feel. Every corner in the world will colourful and energetic by several girls standing. If you boy, a normal bay, I believe that you will try to watch when a beautiful girl passing you and you will nervous if a girl watching you just when you are watching her.

Now give you a surprise that may be never happy in the real time. Millions of PLMM stand in a line and facing you(^_^). They are dress colourful clothings. You should to find out a maximal subline PLMM that their clothing color are all different.

Input
The input contains multiple test cases.
Each case first give a integer n expressing many many girls stand in line.(n<=10000000)
Next line a string including n character, each character standing one girls’s clothing color.

Output
Output one integer the numbers of maximal subline PLMM that their clothing color are all different and the line’s begin and end (based from 0). If their are more answer, print the begin smallest.

Sample Input

3
abc
5
aaaba
8
hdugirls

Sample Output

3 0 2
2 2 3
8 0 7

题目大意:
就是问你给定的序列中最长的连续的不重复的子序列的长度,以及起始位置,如果有多处,输出最前面的一组

题目分析:
首先看数据规模,10^7,至少要搞到o(n)的时间复杂度,先说明一点,题目说的是字符,但是并没有说是小写字母,尽管样例都是小写,所以数组开大点,150或者300都行,接下来说思路,感觉思路就是尺取法,两个指针,一个定在开始,另外一个开始往前扫,把出现的字母的位置存在刚才开的数组里,直到出现重复为止(数组的这个位置已经放过字符)那么这时候就把当前扫描的序列的长度以及起始位置跟原来比较一下,留下长的序列,然后把后面的指针挪到重复的字符的位置的下一个字符。值得注意的一点是,我们并不需要每次在扫描最长的序列之前都对数组进行一次重新赋值,只需要看重复的字符是不是在当前尾指针的右侧(左侧的话跟当前扫描没关系)

代码:

#include "cstdio"
#include "cstring"
int pos[150];
int main()
{
    int n,i,l,r,ltmp,cnt,cnttmp;
    char ch;
    while(scanf("%d",&n)!=EOF)
    {
        getchar();
        ch=getchar();
        cnt=ltmp=0;
        cnttmp=1;
        memset(pos,-1,sizeof(pos));
        pos[ch]=0;
        for(i=1;i<n;i++)
        {
            ch=getchar();
            //出现重复
            if(pos[ch]>=0&&pos[ch]>=ltmp){
                if(cnttmp>cnt){
                    cnt=cnttmp;
                    l=ltmp;
                    r=i-1;
                }
                cnttmp-=pos[ch]-ltmp;
                ltmp=pos[ch]+1;
            }else{
                cnttmp++;
            }
            //不管重不重,都把最新出现的位置放过来
        //因为只有新位置才会影响以后,旧位置的话一定在尾指针之前,没用了
            pos[ch]=i;
        }
        if(cnttmp>cnt){
            cnt=cnttmp;
            l=ltmp;
            r=i-1;
        }
        printf("%d %d %d\n",cnt,l,r);
    }
    return 0;
}

你可能感兴趣的:(HDU,尺取法)