子序列 NYOJ (尺取法+队列+hash) (尺取法+离散化)

Posted joeylee97

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了子序列 NYOJ (尺取法+队列+hash) (尺取法+离散化)相关的知识,希望对你有一定的参考价值。

子序列

时间限制:3000 ms  |  内存限制:65535 KB
难度:5
 
描述

给定一个序列,请你求出该序列的一个连续的子序列,使原串中出现的所有元素皆在该子序列中出现过至少1次。

如2 8 8 8 1 1,所求子串就是2 8 8 8 1。

 
输入
第一行输入一个整数T(0<T<=5)表示测试数据的组数
每组测试数据的第一行是一个整数N(1<=N<=1000000),表示给定序列的长度。
随后的一行有N个正整数,表示给定的序列中的所有元素。
数据保证输入的整数都不会超出32位整数的范围。
输出
对于每组输入,输出包含该序列中所有元素的最短子序列的长度
样例输入
2
5
1 8 8 8 1
6
2 8 8 8 1 1
样例输出
2
5
来源
POJ月赛改编
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<queue>
#include<deque>
#include<iomanip>
#include<vector>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<fstream>
#include<memory>
#include<list>
#include<string>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MAXN 1000044
#define INF 1000000009
#define eps 0.00000001
/*
利用队列从前到后遍历数组元素
当前元素未在之前出现过,更新ans为队列元素个数
当前元素在之前出现过
    如果当前队首元素在hash表中出现次数多于1次,pop
*/
int T, n, aim, a[MAXN],b[MAXN];
typedef struct Hashnode
{
    int data;
    int cnt;
    struct Hashnode* next;
}*List;
typedef struct Hashtb
{
    List* L;
}*HashTable;
HashTable Init()
{
    HashTable H = (HashTable)malloc(sizeof(Hashtb));
    H->L = (List*)malloc(sizeof(List)*MAXN);
    for (int i = 0; i < MAXN; i++)
    {
        H->L[i] = (List)malloc(sizeof(Hashnode));
        H->L[i]->data = 0;
        H->L[i]->cnt = 0;
        H->L[i]->next = NULL;
    }
    return H;
}
int Hash(int x)
{
    return x%MAXN;
}
void clear(HashTable H)
{
    for (int i = 0; i < MAXN; i++)
    {
        H->L[i]->data = 0;
        H->L[i]->cnt = 0;
        H->L[i]->next = NULL;
    }
}
List find(int x, HashTable H)
{
    List l = H->L[Hash(x)];
    List p = l->next;
    while (p != NULL&&p->data != x)
        p = p->next;
    return p;
}
int cnt(int x, HashTable H)
{
    List p = find(x, H);
    if (p == NULL)
        return -1;
    else
    {
        if (p->cnt > 1)
        {
            p->cnt--;
            return p->cnt + 1;
        }
        else
            return p->cnt;
    }
}
bool Insert(int x, HashTable H)
{
    List l = H->L[Hash(x)];
    List p = find(x, H);
    if (!p)
    {
        List tmp = (List)malloc(sizeof(Hashnode));
        tmp->data = x;
        tmp->cnt = 1;
        tmp->next = l->next;
        l->next = tmp;
        return false;
    }
    else
    {
        p->cnt++;
        return true;
    }
}
int main()
{
    scanf("%d", &T);
    HashTable H = Init();
    while (T--)
    {
        clear(H);
        scanf("%d", &n);
        int ans = INF,tmp;
        queue<int> q;
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &tmp);
            if (!Insert(tmp,H))
            {
                q.push(tmp);
                ans = q.size();
            }
            else
            {
                q.push(tmp);
                while (!q.empty()&&cnt(q.front(),H) > 1)
                {
                    q.pop();
                }
                ans = min(ans,(int)q.size());
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

以上是关于子序列 NYOJ (尺取法+队列+hash) (尺取法+离散化)的主要内容,如果未能解决你的问题,请参考以下文章

POJ3162 Walking Race(树形DP+尺取法+单调队列)

尺取法--连续子序列

POJ 3061 Subsequence ( 二分 || 尺取法 )

尺取法

毛虫算法——尺取法

CodeForces - 958 F2 Lightsabers (medium) . (尺取法)