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

来源:互联网 发布:手机淘宝查看历史订单 编辑:程序博客网 时间:2024/05/10 23:48

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

LRU CachingTime 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 1ABCCDEAFDEAFBSimulation 2WYZWYXWXYSimulation 3EIO
题意:

存储器大小为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;}


原创粉丝点击