hnuoj LRU Caching (链表,结构体指针 / vector)

http://acm.hnu.cn/online/?action=problem&type=show&id=12763

LRU Caching
Time Limit: 3000ms, Special Time Limit:7500ms, Memory Limit:65536KB
 
Problem description

When accessing large amounts of data is deemed too slow, a common speed up technique is to keep a small amount of the data in a more accessible location known as acache. The first time a particular piece of data is accessed, the slow method must be used. However, the data is then stored in the cache so that the next time you need it you can access it much more quickly. For example, a database system may keep data cached in memory so that it doesn't have to read the hard drive. Or a web browser might keep a cache of web pages on the local machine so that it doesn't have to download them over the network.

In general, a cache is much too small to hold all the data you might possibly need, so at some point you are going to have to remove something from the cache in order to make room for new data. The goal is to retain those items that are more likely to be retrieved again soon. This requires a sensible algorithm for selecting what to remove from the cache. One simple but effective algorithm is the Least Recently Used, or LRU, algorithm. When performing LRU caching, you always throw out the data that was least recently used.

As an example, let's imagine a cache that can hold up to five pieces of data. Suppose we access three pieces of data—A, B, and C. As we access each one, we store it in our cache, so at this point we have three pieces of data in our cache and two empty spots (Figure 1). Now suppose we access D and E. They are added to the cache as well, filling it up. Next suppose we access A again. A is already in the cache, so the cache does not change; however, this access counts as a use, making A the most recently used. Now if we were to access F, we would have to throw something out to make room for F. At this point, B has been used least recently, so we throw it out and replace it with F (Figure 2). If we were now to access B again, it would be exactly as the first time we accessed it: we would retrieve it and store it in the cache, throwing out the least recently used data—this time C—to make room for it.

 
Figure 1: Cache after A, B, CFigure 2: Cache after A, B, C, D, E, A, F

Your task for this problem is to take a sequence of data accesses and simulate an LRU cache. When requested, you will output the contents of the cache, ordered from least recently used to most recently used.

Input

The input will be a series of data sets, one per line. Each data set will consist of an integer N and a string of two or more characters. The integer N represents the size of the cache for the data set (1 ≤ N ≤ 26). The string of characters consists solely of uppercase letters and exclamation marks. An upppercase letter represents an access to that particular piece of data. An exclamation mark represents a request to print the current contents of the cache.

For example, the sequence ABC!DEAF!B! means to acces A, B, and C (in that order), print the contents of the cache, access D, E, A, and F (in that order), then print the contents of the cache, then access B, and again print the contents of the cache.

The sequence will always begin with an uppercase letter and contain at least one exclamation mark.

The end of input will be signaled by a line containing only the number zero.

Output

For each data set you should output the line "Simulation S", where S is 1 for the first data set, 2 for the second data set, etc. Then for each exclamation mark in the data set you should output the contents of the cache on one line as a sequence of characters representing the pieces of data currently in the cache. The characters should be sorted in order from least recently used to most recently used, with least recently occuring first. You only output the letters that are in the cache; if the cache is not full, then you simply will have fewer characters to output (that is, do not print any empty spaces). Note that because the sequence always begins with an uppercase letter, you will never be asked to output a completely empty cache.

Sample Input
5 ABC!DEAF!B!
3 WXWYZ!YZWYX!XYXY!
5 EIEIO!
0
Sample Output
Simulation 1
ABC
CDEAF
DEAFB
Simulation 2
WYZ
WYX
WXY
Simulation 3
EIO
题意:

存储器大小为n,即可放n个字母,如样例3,先放入E,它放在存储器的最底端,再放入I,当输入第三个字母E时,因为前面E已经出现过,只需要把前面的E提到最上面来即可,不能放入第二个E。当输入“!”时,它不入存储器,而是表示要输出此时存储器中的字母,从底向上输出。如果存储器已满,再放入第六个未出现过的字母时,最底下的那个字母将被删掉。

思路:

用链表模拟。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
char a[2000000];
struct node
{
    char c;
    node  *next;
}head,*tail;
int main()
{
    int n,i,j,len,m,cas=1;
    while(scanf("%d",&n)&&n!=0)
    {
        int ch[27]={0};
        printf("Simulation %d\n",cas++);
        scanf("%s",a);
        len=strlen(a);
        head.next=NULL;
        ch[a[0]-'A']=1;
        m=1;
        node no;
        tail=&no;
        tail->c=a[0];
        tail->next=NULL;
        head.next=tail;
        for(i=1;i<len;i++)
        {

            if(a[i]!='!')
            {
          //刚开始直接用node  p;结果i++再进入if的时候,p的地址没变,tail那里也形成了环,错了很久;
         //后来malloc后,又在m++那里用了free(p);结果相当于最终的 fail地址也被释放掉了。去掉free(p)才算解决。
              node *p;
              p=(node *) malloc(sizeof(node)); 
              p->c=a[i];
              p->next=NULL;
              tail->next=p;
              tail=p;
              m++;
              if(ch[a[i]-'A']==1)
              {
                  node *t=&head;
                  while(t->next!=tail)
                  {
                      if(t->next->c==tail->c)
                      {
                          t->next=t->next->next;
                          m--;
                          break;
                      }
                      t=t->next;
                  }
              }
              ch[a[i]-'A']=1;
             if(m>n)
             {
                 ch[head.next->c-'A']=0;
                 head.next=head.next->next;
                 m--;
             }
            }
            else
            {
                node *x=head.next;
                int kk=m;
                while(kk--)
                {
                    printf("%c",x->c);
                    if(x->next==NULL)break;
                    x=x->next;
                }
                printf("\n");
            }
        }

    }
    return 0;
}

直接用vector模拟:

#include<map>
#include<set>
#include<vector>
#include<cstdio>
#include<cstring>
#include <iostream>
using namespace std;
char s[1000009];
int main()
{
    int n,i,cas=1;
    while(scanf("%d",&n)&&n)
    {
        scanf("%s",s);
        printf("Simulation %d\n",cas++);
        vector<char > t;
        int a[27]={0};
        t.push_back(s[0]);
        a[s[0]-'A']=1;
        for(i=1;s[i];i++)
        {
            if(s[i]=='!')
            {
                vector<char >::iterator g=t.begin();
                while(g!=t.end())
                {
                    printf("%c",*g);
                    g++;
                }
                printf("\n");
                continue;
            }
            if(a[s[i]-'A']==1)
            {
                vector<char >::iterator k=t.begin();
                while(k!=t.end())
                {
                    if(*k==s[i])
                    {
                        t.erase(k);
                        break;
                    }
                    k++;
                }
                t.push_back(s[i]);
            }
            else
            {
                a[s[i]-'A']=1;
                t.push_back(s[i]);
                if(t.size()>n)
                {
                    a[*t.begin()-'A']=0;
                     t.erase(t.begin());

                }

            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值