【算法学习笔记】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. */