STL习题

复合词

原题:UVa 10391

算法

这题我一开始是拼接来做的结果超时,部分代码如下:

for(int i = 0; i < cnt; i++){
   for(int j = i + 1; j < cnt; j++){
     s1 = words[i] + words[j];
     s2 = words[j] + words[i];
     if(dict.count(s1)) cout << s1 << "\n";
     if(dict.count(s2)) cout << s2 << "\n";
   }
 }

这里的时间复杂度有O(n²)了,换一种思考方式,改成字符串分割,因为每个字符串长度不一,所以时间复杂度为O(mn),结果通过了,其中用到了 string类里面的 substr()函数,具体用法参见下面的代码

程序代码

#include <iostream>
#include <string>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;

const int maxn = 120000 + 5;
set<string> dict;
string words[maxn];
int main(){
//  freopen("input.txt", "r", stdin);
  string s;
  int cnt = 0;
  dict.clear();
  while(cin >> s){ 
    dict.insert(s);
    words[cnt] = s;
    cnt++;
  }
  string a, b;
  for(int i = 0; i < cnt; i++){
    for(int j = 0; j < words[i].size() - 1; j++){
      a = words[i].substr(0,j + 1);//从下标为0的元素开始到长度为j+1的元素结束
      if(!dict.count(a)) continue;
      b = words[i].substr(j + 1);//从下标为j+1的元素开始,到字符串结束
      if(!dict.count(b)) continue;
      cout << words[i]<<"\n";
      break;
    }
  }
  return 0;
}

打印队列

原题:UVa 12100

算法

用一个普通队列来放任务,用一个优先队列来按优先级放任务,如果普通队列里的队首元素在优先级队列里也是队首,则出列,否则放到队尾。

程序代码

#include <cstdio>
#include <queue>
using namespace std;

struct project{
  int x;
  int flag;
};
queue<project> q;
priority_queue<int> pq;

int main(int argc, char const *argv[])
{
  int T;
  scanf("%d", &T);
  while(T--){
  while(!q.empty()) q.pop();
  while(!pq.empty()) pq.pop();
  int n,t;
  project m;
  scanf("%d%d", &n, &t);
  for(int i = 0; i < n; i++){
    scanf("%d", &m.x);
    m.flag = 0;
    if(i == t) m.flag = 1;//记录关注的任务
    q.push(m);
    pq.push(m.x); 
  }
  int cnt = 0;
  while(1){
    project t1;
    int t2;
    t1 = q.front();
    t2 = pq.top();
    if(t1.x == t2 && t1.flag) {cnt++; printf("%d\n", cnt);break;}
    else if(t1.x == t2 && !t1.flag){
      cnt++;
      q.pop();
      pq.pop();
    }
    else{
      q.pop();
      q.push(t1);
    }
  }
  }
  return 0;
}

图书馆管理系统

原题:UVa 230

算法

字符串变成数字来处理,这个思想很重要!!!将字符串变成数字后,无论是排序,还是插入删除,都会简单不少,而且速度更快;其他其实没什么算法,不过有点烦而已,要细心。

程序代码

#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

struct book{
  string title;
  string author;
  //重载图书排序方式
  bool operator < (const book& ob){
    if(this->author == ob.author) return this->title < ob.title;
    return this->author < ob.author;    
  }
};

vector<book> All_books;// 存储所有图书信息
map<string, int> ID;//每本书对应一个唯一的ID
vector<int > LIB;//图书馆中现存的书
vector<int > SHELVE;//已经还来的书,还未上架
int main(int argc, char const *argv[])
{
 // freopen("input.txt", "r", stdin);
  string s;
  book tb;

  while(getline(cin, s)){
    if(s[0] == 'E') break;

    int t = s.find("by", 0);
    tb.title = s.substr(0, t - 1);
    tb.author = s.substr(t + 3);
    All_books.push_back(tb);//按格式分割字符串后存储每一本图书
  }
  sort(All_books.begin(), All_books.end());
  for(int i = 0; i < All_books.size(); i++){
    ID[All_books[i].title] = i;//未每本书建立唯一的ID,作者可能相同但书名不会
    LIB.push_back(i);
  }
  while(getline(cin, s)){
    //结束操作
    if(s[0] == 'E') break;
    //借书
    if(s[0] == 'B'){
      string temp = s.substr(7);
      int t = ID[temp];
      int i = 0,size = LIB.size();
      while(LIB[i] != t) i++;//找到目标书籍的ID
      for(; i < size - 1; i++){
        LIB[i] = LIB[i + 1];
      }
      LIB.resize(size - 1);//更改现存的书的数量
    }
    //还书
    if(s[0] == 'R'){
      string temp = s.substr(7);
      int t = ID[temp];
      SHELVE.push_back(t);//放到待还书架上
    }
    if(s[0] == 'S'){
      sort(SHELVE.begin(), SHELVE.end());
      for(int i = 0; i < SHELVE.size(); i++){
        //如果图书馆没书了
        if(LIB.size()== 0){
          LIB.push_back(SHELVE[i]);
          cout << "Put " << All_books[SHELVE[i]].title <<" first" << "\n";
        }
        else{
            int size = LIB.size();
            int j = 0;
            while(SHELVE[i] > LIB[j] && j < size) j++;//找到插入位置
            LIB.push_back(-1);//为放上来的书预留一个空位
            for( int k = size; k > j; k--){
              LIB[k] = LIB[k - 1];
            }    
            LIB[j] = SHELVE[i];
            if(j > 0)//插入的位置不是首位
            cout << "Put " << All_books[LIB[j]].title << " after "
            << All_books[LIB[j - 1]].title << "\n";
            else//放在首位
            cout << "Put " << All_books[SHELVE[j]].title <<" first" << "\n";   
        } 
      }
      SHELVE.clear();//清空书架
      cout <<"END\n";
    }
  }
  return 0;
}

集合栈计算机

原题:UVa 12096

算法

同样是字符串变成数字来处理

程序代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <set>
#include <vector>
#include <stack>
#include <map>
using namespace std;

typedef set<int> Set;
map<Set,int> IDcache;
vector<Set> Setcache;

int ID(Set x){
    if(IDcache.count(x)) return IDcache[x];
    Setcache.push_back(x);
    return IDcache[x] = Setcache.size()-1;
}

#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x,x.begin())

stack<int> s;

int main(){
    int n,T;
    scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        while(!s.empty()) s.pop();
        for(int i = 0; i < n; i++){
            string op;
            cin >> op;
            if (op[0] == 'P') s.push(ID(Set()));
            else if (op[0] == 'D') s.push(s.top());
            else {
                Set x1 = Setcache[s.top()]; s.pop();
                Set x2 = Setcache[s.top()]; s.pop();
                Set x;
                if (op[0] == 'U') set_union (ALL(x1), ALL(x2), INS(x));
                if (op[0] == 'I') set_intersection (ALL(x1), ALL(x2), INS(x));
                if (op[0] == 'A') { x = x2; x.insert(ID(x1));}
                s.push(ID(x));
            }
            cout << Setcache[s.top()].size()  << endl;
        }
        cout << "***" <<endl;
    }
    return 0;
}

数据库

原题:UVa 1592

算法

算法同上,用数字编号进行预处理

程序代码

#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <sstream>
using namespace std;

typedef pair<int, int> PII;

const int maxcol = 10 + 5;
const int maxrow = 10000 + 5;

int n, m, cnt, db[maxrow][maxcol];
map<string, int> id;

int ID(const string& s){
    if(!id.count(s)){
      id[s] = ++cnt;
    }
    return id[s];
}

void find(){
  for(int c1 = 0; c1 < m; c1++)
    for(int c2 = c1 + 1; c2 < m; c2++){
    map<PII,int> d;
    for(int r = 0; r < n; r++){
      PII p = make_pair(db[r][c1], db[r][c2]);
      if(d.count(p))
      {
        printf("NO\n");
        printf("%d %d\n", d[p] + 1, r + 1);
        printf("%d %d\n", c1 + 1, c2 + 1);
        return ;
      } 
      d[p] = r;
    }
  }
  printf("YES\n");
}

int main(){
 // freopen("input.txt", "r", stdin);
  string s;
  while(getline(cin, s)){
    stringstream ss(s);
    if(!(ss >> n >> m)) break;
    cnt = 0;
    id.clear();
    for(int i = 0; i < n; i++){
      getline(cin, s);
      int lastpos = -1;
      for(int j = 0; j < m; j++){
          int p = s.find(',',lastpos + 1);
          if(p == string::npos) p = s.length();
          db[i][j] = ID(s.substr(lastpos + 1, p - lastpos -1));
          lastpos = p;
        }
    }  
     find();
  }
}

找bug

原题:UVa 1596

算法

用栈来保存 [],用 map来保存数组,这一题比较繁琐,首先考虑是赋值语句还是定义语句,就是看有没有“=”,定义语句比较简单,变量名直接放到map里,再用一个map保存该数组的长度。如果是赋值语句,就要考虑一下情况:

  • 是否存在变量名
  • 如果是嵌套的话,每一层嵌套的值在外层的数组中有没有超过外层数组的长度
  • 如果没有超过长度,每一层嵌套的值在外层的数组中是否被赋值

程序代码

#include <iostream>
#include <map>
#include <string>
#include <stack>
using namespace std;

map<char, map<int, int> > dict;
map<char, int> d2;
stack<char > nameache;

int main(int argc, char const *argv[])
{

  string s;
  int flag = 0;//用来识别是否为.的标志
  int bug_flag = 0;//是否出现bug
  int line = 0;
  while(getline(cin, s))
  {
    if(bug_flag == 1 && s[0] != '.') continue;
    if(s == "." && flag == 0){
      flag++;
      if(!bug_flag) cout <<"0\n";
      bug_flag = 0;
      dict.clear();
      d2.clear();
      line = 0;
      while(!nameache.empty()) nameache.pop();
      continue;
    }
    if(s == "." && flag == 1){break;}
    flag = 0;
    ++line;
    //定义
    if(s.find("=") == string::npos)
     {

      int k = 2, num = 0;
      while(s[k] != ']'){
        num *= 10;
        num += s[k] - '0';
        ++k;
      }
      d2[s[0]] = num;
    }
    //赋值
    else{
      int pos = s.find("=");
      int i = 0, num = 0;
      while(s[i] != ']'){
        if(isalpha(s[i])) {
          if(!d2.count(s[i])) {cout << line << endl; bug_flag = 1; break;}
          nameache.push(s[i]);
          }
        else if(s[i] == '[') {i++;continue;}
        else if(s[i] >= '0' && s[i] <= '9'){
          num *= 10;
          num += s[i] - '0';
        }
        i++;
      }
      if(bug_flag) continue;
      int t = num, left;
      char ch, chleft;
      while(nameache.size() > 1){
        ch = nameache.top();
        if(!d2.count(ch)){cout << line << endl; bug_flag = 1; break;}
        if(t >= d2[ch]) {cout << line << endl; bug_flag = 1; break;}
        if(!dict[ch].count(t)){cout << line << endl; bug_flag = 1; break;}
        nameache.pop();
        t = dict[ch][t];
      }
      if(bug_flag) continue;
      ch = nameache.top(); nameache.pop();
      if(!d2.count(ch)){cout << line << endl; bug_flag = 1; continue;}
      if(t >= d2[ch]) {cout << line << endl; bug_flag = 1; continue;}
      left = t;
      chleft = ch;
      i = pos + 1;

      num = 0;

      if(s[i] >= '0' && s[i] <= '9'){
        while(s[i]!='\0'){
          num *= 10;
          num += s[i] - '0';
          ++i;
        }
        dict[chleft][left] = num;
        continue;
      }
      while(s[i] != ']'){
        if(isalpha(s[i])) {
          if(!d2.count(s[i])) {cout << line << endl; bug_flag = 1; break;}
          nameache.push(s[i]);
          }
        else if(s[i] == '[') {i++;continue;}
        else if(s[i] >= '0' && s[i] <= '9'){
          num *= 10;
          num += s[i] - '0';
        }
        i++;
      }
      if(bug_flag) continue;
      t = num;
      while(!nameache.empty()){
        ch = nameache.top();
        if(!d2.count(ch)){cout << line << endl; bug_flag = 1; break;}
        if(t >= d2[ch]) {cout << line << endl; bug_flag = 1; break;}
        if(!dict[ch].count(t)){cout << line << endl; bug_flag = 1; break;}
        nameache.pop();
        t = dict[ch][t];
      }
      if(!bug_flag)
      dict[chleft][left] = t;
    }
  }
  return 0;
}