【算法学习笔记】50.字符串处理 SJTU OJ 1361 丁姐的周末

Description

丁姐来到了神秘的M78星云,为了成为和凹凸曼一样强大的男人有朝一日回到地球拯救世界,丁姐开始了刻苦的学习。但丁姐先要知道在M78星云上一周有多少天,这样他才能知道什么时候是周末可以带妹子出去玩。他找到一个老凹凸曼,但是老凹凸曼自己记性不太好,偶尔会告诉他错误的信息。

凹凸曼会告诉丁姐如下格式的信息:

Today is xxxday.

Yesterday was yyyend.

Tomorrow will be zzzday.

规则1: xxx/yyy/zzz为任意字符串,以day结尾的单词代表工作日,以end结尾的单词代表周末。

规则2: Today is xxxxx. 总是正确的。

规则3: Yesterday was xxxxx. 是正确的,当且仅当在上文中出现过xxxxx。

规则4: Tomorrow will be xxxxx. 是正确的,当且仅当在下文中出现过xxxxx。

规则5: xxxxx被认为是合法的一天,当且仅当至少有一句包含xxxxx的信息是正确的。

请你帮丁姐计算出在M78星云上一周有几天?周末有几天?

Input Format

第1行,一个数字n,表示总共有n条信息。

第2到n+1行,一条具体的信息。

Output Format

两个整数A和B,表示一周共有A天,周末有B天。

Sample Input

6
Today is sunday. // 工作日
Yesterday was friday. // 错误
Tomorrow will be ksnsend. // 错误
Yesterday was friday. // 工作日
Today is tuesdayend. // 周末
Yesterday was sunday. // 工作日,重复

Sample Output

3 1

Limit

n <= 1000

50%测试数据只有Today

思路很简单。就是很麻烦,条件很多容易出错。尤其是判断前后文的问题,要考虑字符串包含的特殊情况。

#include <iostream>
#include <cstdio>
#define MaxN 1000+10
using namespace std;

int day_len = 0;//存储day的个数
int end_len = 0;//存储end的个数
string ori[MaxN];//存数输入的原话
string inputs[MaxN];//存数day和end的名字 具体类型 用type存储

int weekdays[MaxN];//存储的是确定第i个day所用的是第几句话
int weekends[MaxN];//存储的是确定第i个end所用的是第几句话

int inputs_type[MaxN]; //存储每个输入的类型 0是day 1是end

int n;//一共有n句话

//判断是否在j之前出现过test
bool occur_formor(string test,int j,int type){
    for (int i = 1; i < j; ++i)
    {
        if(test == inputs[i] and type == inputs_type[i])
            return true;
    }
    return false;
}

//判断是否在j之后出现过test
bool occur_post(string test,int j,int type){
    if(type==1)
        test += "end";
    else
        test += "day";
    for (int i = j+1; i <= n; ++i)
    {
        if(ori[i]=="Today is "+test+".")
            return true;
        if(ori[i]=="Yesterday was "+test+".")
            return true;
        if(ori[i]=="Tomorrow will be "+test+".")
            return true;
    }
    return false;
}

//判断是否出现过test+day
bool have_in_weekday(string test){

    for (int i = 0; i < day_len; ++i) //遍历所有的确定过的day
    {
        int id = weekdays[i];//得到确定那个day的inputs的编号
        if(inputs[id] == test and inputs_type[id]==0)
            return true;
    }
    return false;
}
//判断是否出现过test+end
bool have_in_weekend(string test){

    for (int i = 0; i < end_len; ++i)
    {
        int id = weekends[i];
        if(inputs[id] == test and inputs_type[id]==1)
            return true;
    }
    return false;
}

//尝试加入一个数i是句子编号 xxx是天的名字 type是种类
void add(int type, string xxx,int i){
    if(type==1 and !have_in_weekend(xxx)){
        weekends[end_len++] = i;
    }else if(type==0 and !have_in_weekday(xxx)){
        weekdays[day_len++] = i;
    }
    return;
}

string getXXX(string s,string seg){
    int start = s.find(seg)+seg.size();
    return s.substr(start, s.size()-4-start);
}

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

    cin>>n;
    getchar();//去除回车

    //存储原始输入 以便处理"下文" 的条件
    for (int i = 1; i <= n; ++i)
    {
        getline(cin,ori[i]);
    }

    //开始处理输入
    for (int i = 1; i <= n; ++i)
    {
        string& s = ori[i]; 

        //根据前5个字符来判断输入的是今天 昨天 明天
        string flag = s.substr(0,5);//flag用于判断是哪种输入

        string xxx;//day或者end的名字

        int type;//记录 1是end 0是day

        //根据倒数第二个字符来判断输入天的类型
        if(s[s.size()-2]==‘d‘)//xxxend.
            type = 1;//end是1
        else
            type = 0;//day是0

        //如果说的是今天
        if(flag=="Today"){
            xxx = getXXX(s,"Today is ");
            add(type,xxx,i);
        }else if(flag=="Yeste"){
            xxx = getXXX(s,"Yesterday was ");
            if(occur_formor(xxx,i,type))//如果前文提到过
                add(type,xxx,i);
        }else if(flag =="Tomor"){
            xxx = getXXX(s,"Tomorrow will be ");
            if(occur_post(xxx,i,type))//如果后文提到过
                add(type,xxx,i);
        }
        inputs_type[i] = type;
        inputs[i] = xxx;
    }

    cout<<end_len + day_len<<" "<<end_len<<endl;
    return 0;
}

/*
6
Today is sunday.
Yesterday was friday.
Tomorrow will be ksnsend.
Yesterday was friday.
Today is tuesdayend.
Yesterday was sunday.

2
Tomorrow will endday.
Today is enddayday.

 */
时间: 2024-12-27 21:01:20

【算法学习笔记】50.字符串处理 SJTU OJ 1361 丁姐的周末的相关文章

【算法学习笔记】63. BFS SJTU OJ 1281 蹦蹦跳跳

典型的BFS,找到起点直接进行搜搜即可.要注意的就是层数的处理.坐标到id的转换.还有就是要尽早判断是否达到终点. 代码注释很详细,最后面两个函数是一开始写的 用抽取邻接矩阵+Dijkstra 来算的,很麻烦 头脑一热的结果.. #include <vector> #include <queue> #include <iostream> using namespace std; int map[31][31]={0}; int M,N,M1,M2; struct Poi

【算法学习笔记】31.动态规划 SJTU OJ 1320 numtri

Description Consider the number triangle shown below. Write a program that calculates the highest sum of numbers that can be passed on a route that starts at the top and ends somewhere on the base. Each step can go either diagonally down to the left

【算法学习笔记】68.枚举 SJTU OJ 1272 写数游戏

很简单 不用太考虑效率 虽然每次都要重新排序 注意vector的使用,非常便利. 还有一个技巧就是用一个have型bool数组来记录是否存在. #include <iostream> #include <vector> #include <algorithm> using namespace std; bool have[1000] = {0}; vector<int> v; //用vector来实现动态数组的简便性 bool cmp_int(const i

算法学习笔记 KMP算法之 next 数组详解

最近回顾了下字符串匹配 KMP 算法,相对于朴素匹配算法,KMP算法核心改进就在于:待匹配串指针 i 不发生回溯,模式串指针 j 跳转到 next[j],即变为了 j = next[j]. 由此时间复杂度由朴素匹配的 O(m*n) 降到了 O(m+n), 其中模式串长度 m, 待匹配文本串长 n. 其中,比较难理解的地方就是 next 数组的求法.next 数组的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀,也可看作有限状态自动机的状态,而且从自动机的角度反而更容易推导一些. "前

由LCS到编辑距离—动态规划入门—算法学习笔记

一切计算机问题,解决方法可以归结为两类:分治和封装.分治是减层,封装是加层. 动态规划问题同样可以用这种思路,分治. 它可以划分为多个子问题解决,那这样是不是用简单的递归就完成了?也许是的,但是这样会涉及太多的不便的操作.因为子问题有重叠! 针对这种子问题有重叠的情况的解决,就是提高效率的关键. 所以动态规划问题可以总结为:最优子结构和重叠子问题. 解决这个子问题的方式的关键就是:memoization,备忘录. 动态规划算法分以下4个步骤: 描述最优解的结构 递归定义最优解的值 按自底向上的方

KMP算法 学习笔记

kmp算法在很多人看来是如此的厉害,很早之前就学过了,但是各种看不懂把我拦住了,现在重新拾取,来写一下个人的学习总结. kmp看毛片算法(小甲鱼教的)(在这给小甲鱼做个广告,我个人看来小甲鱼讲的数据结构很好,很有趣.个人创业不容易,希望大家多多支持www.fishc.com小甲鱼,我跟小甲鱼素不相识,只是有用的东西大家分享) 好了言归正传. 如果你之前看过kmp算法没有看懂希望在这不要带着一种恐惧感,如果你没看过那是更好. 网上有很多详细教程,但是大部分都很啰嗦,容易把人看晕. kmp算法没有什

算法学习笔记 递归之 快速幂、斐波那契矩阵加速

递归的定义 原文地址为:http://blog.csdn.net/thisinnocence 递归和迭代是编程中最为常用的基本技巧,而且递归常常比迭代更为简洁和强大.它的定义就是:直接或间接调用自身.经典问题有:幂运算.阶乘.组合数.斐波那契数列.汉诺塔等.其算法思想: 原问题可分解子问题(必要条件): 原与分解后的子问题相似(递归方程): 分解次数有限(子问题有穷): 最终问题可直接解决(递归边界): 对于递归的应用与优化,直接递归时要预估时空复杂度,以免出现用时过长或者栈溢出.优化递归就是以

Swift学习笔记(4)--字符串及基本使用

String是例如"hello, world","海贼王" 这样的有序的Character(字符)类型的值的集合,通过String类型来表示. Swift 的String类型与 Foundation NSString类进行了无缝桥接.如果您利用 Cocoa 或 Cocoa Touch 中的 Foundation 框架进行工作.所有NSString API 都可以调用您创建的任意String类型的值.除此之外,还可以使用本章介绍的String特性.您也可以在任意要求传

EM算法学习笔记2:深入理解

文章<EM算法学习笔记1:简介>中介绍了EM算法的主要思路和流程,我们知道EM算法通过迭代的方法,最后得到最大似然问题的一个局部最优解.本文介绍标准EM算法背后的原理. 我们有样本集X,隐变量Z,模型参数θ,注意他们3个都是向量,要求解的log似然函数是lnp(X|θ),而这个log似然函数难以求解,我们假设隐变量Z已知,发现lnp(X,Z|θ) 的最大似然容易求解. 有一天,人们发现引入任意一个关于隐变量的分布q(Z),对于这个log似然函数,存在这样一个分解: lnp(X|θ)=L(q,θ