小明和他的好朋友小西在玩一个新的游戏,由小西给出一个由小写字母构成的字符串,小明给出另一个比小西更长的字符串,也由小写字母组成,如果能通过魔法转换使小明的串和小西的变成同一个,那么他们两个人都会很开心。这里魔法指的是小明的串可以任意删掉某个字符,或者把某些字符对照字符变化表变化。如:
小西的串是 abba;
小明的串是 addba;
字符变化表 d b (表示d能转换成b)。
那么小明可以通过删掉第一个d,然后将第二个d转换成b将串变成abba。
现在请你帮忙判断:他们能不能通过魔法转换使两个人的串变成一样呢?
Input
首先输入T,表示总共有T组测试数据(T <= 40)。
接下来共T组数据,每组数据第一行输入小西的字符串,第二行输入小明的字符串(数据保证字符串长度不超过1000,小明的串的长度大于等于小西的,且所有字符均为小写字母)。接着输入字母表,先输入m,表示有m个字符变换方式(m< = 100),接着m行每行输入两个小写字母,表示前一个可以变为后一个(但并不代表后一个能变成前一个)。
Output
对于每组数据,先输出Case数。
如果可以通过魔法转换使两个人的串变成一样,输出“happy”,
否则输出“unhappy”。
每组数据占一行,具体输出格式参见样例。
Sample Input
2
abba
addba
1
d b
a
dd
0
Sample Output
Case #1: happy
Case #2: unhappy
题目链接
参考题解
题目中给定两个字符串,第二个长度一定是大于等于第一个的,在下面会给出字母变换表,即可以由某个字母变化成某个字母,如果第二个字符串可以通过删除字符或者或者是对应变化表变化之后能后变成第一个字符串,那么输出“happy”,否则输出“unhappy”。
我们可以用一个二维数组来记录字母的变化表,然后遍历字符串,遇到与第一个字符串中不同的字符就看一下能不能对应上变化表,能的话,就说明能匹配上,否则就往跳到下一个字符,相当于将第二个字符串当前字符删除掉。只要将第一个字符串遍历完就可以,第二个字符串剩下的那些都直接删除就可以了。
AC代码:
#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
const int maxn = 1005;
char str1[maxn], str2[maxn];
int vis[30][30]; //记录变化表,从前一个变到后一个
int main()
{
int t;
scanf("%d", &t);
for(int k = 0; k < t; k++)
{
memset(vis, 0, sizeof(vis));
int len1, len2;
scanf("%s", str1);
scanf("%s", str2);
len1 = strlen(str1);
len2 = strlen(str2);
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
char a,b;
getchar();
scanf("%c %c", &a, &b);
vis[a - 'a'][b - 'a'] = 1; //记录转换表
}
int j = 0, flot = 0;
for(int i = 0; i < len1; i++)
{
if(str1[j] == str2[i]) //如果相等不需要做出任何变化
{
j++;
continue;
}
while(1) //判断是否可转换,不能B跳转到下个字符,A不变
{
//执行到这一步说明这两个字符不相同,但是已经到了第二个字符串的最后一个的下一个了,说明没有与第一个字符串的字符相匹配的了,退出
if(j == len2)
{
flot = 1;
break ;
}
if(vis[str2[j] - 'a'][str1[i] - 'a'] == 1 || str1[i] == str2[j]) //如果可以转化,或者是这两个字符是相同的,那么匹配好,进行下一个
{
j++;
break ;
}
else //如果这两个字符无法匹配,那么就跳过,相当与删除操作
j++;
}
//j>len2-1有两种情况,一种是j==len2,说明无法匹配并且已经到了最后,另一种是j==len2-1,很顺利的匹配下来
if(j >= len2 - 1) break;
}
if(flot != 0)
printf("Case #%d: unhappy\n",k+1);
else
printf("Case #%d: happy\n",k+1);
}
return 0;
}