USACO Contact IOI’98 TLE

毕设的东西做不下了,做点其他东西调节一下,翻出USACO Trainning继续做,到Contact这道题了,光荣地挂在了第7组数据了,写的稍微有点暴力,过段时间再把它过掉吧。

题意是这样的,有一个01串,长度200,000,有1<=A,B<=12,1<=N<=50,求的是串中长度在A,B之间的子串出现次数的统计问题。

想了个最糟糕情况为12*200000=2.4*10^6的算法,最暴力的方法,遍历所有的子串,主要是要怎么hash一个子串,将一个子串唯一映射成一个整数,0011和11是不同的子串,想了个比较巧妙的方法,把空串想为字符0,于是0011可以用1122来表示11用1122来表示,即可以压缩成一个三进制数,然后就可以方便实现了。

PS:题目好烦人,输入拆成若干行,输出又乱拆。

TLE:遍历子串有点暴力,可以尝试下记录之前的信息来递归,小小优化一下到LEN*(B-A)。

Usaco_Contact

TLE的代码如下:

/*
ID: litstrong
PROG: contact
LANG: C++
*/
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <stdio.h>
using namespace std;
 
const int MAX = 600005;
const int LEN = 200005;
 
int A, B, N;
char ch[LEN];
 
class CNODE
{
public:    
    string num;
    int cnt;
public:
    CNODE () : cnt(0) {}
    void AddCnt() { cnt++; }
    bool operator < (const CNODE &t) const
    {
        if(cnt != t.cnt)  return cnt > t.cnt;
        if(num.length() != t.num.length())  
            return num.length() < t.num.length();
        return num < t.num;
    }
}node[MAX];
 
 
 
int main()
{
    freopen("contact.in", "r", stdin);
    freopen("contact.out", "w", stdout);
 
    string mo = "";
    scanf("%d%d%d", &A, &B, &N);
    while(scanf("%s", ch) != EOF)  mo += ch;
    
    int len = mo.length();
    int len_max = 0;
    for(int i = 0; i <= len - A; i++)
    {
        string dq = "";
        int tmp = 0, thr = 1;
        for(int j = 0; j < B; j++) 
        {
            dq.push_back(mo[i + j]);
            tmp += (mo[i + j] - '0' + 1) * thr;
            thr *= 3;
            if(j < A - 1)  continue;
            if(i + j >= len)  break;
 
            node[tmp].num = dq;
            node[tmp].AddCnt();
 
            len_max = max(len_max, tmp);
        }
    }
 
    sort(node, node + len_max + 1);
 
    int before = 0, in = 0, first = 0, dqCnt = 1;
    int zNum = 0;
    for(int i = 0; i <= len_max; i++)
    {
        if(node[i].cnt)
        {
            if(node[i].cnt != before && first)  
            {
                if(++dqCnt > N)  break;
 
                printf("\n");
                in = 0;
                zNum = 0;
            }
            first = 1;
 
            if(in == 0 && zNum == 0)  printf("%d\n", node[i].cnt);
 
            if(in == 0)  cout << node[i].num;
            else  cout << " " << node[i].num;
 
            in = 1;    
            zNum++;
            if(zNum % 6 == 0) 
            {
                in = 0;
                printf("\n"); 
            }
 
            before = node[i].cnt;            
        }
    }
    printf("\n");
}
原文地址:https://www.cnblogs.com/litstrong/p/1994419.html