传送门:codeforces 883F
题目大意:
字符 u 和 oo 等价,字符 h 和 kh等价,问给出的 n 个字符串中不同的串有多少个。注意 kkkkh 是和 h 等价的,因为可以通过多步替换得到, ooo 的情况可以等价为 ou 或 uo。
思路:
大体思路是先按照规则把串替换,然后看有多少个不同的串。在判断有多少不同串的时候可以先排序,如果相邻两个串不同则结果 +1. 由于用到字符串的排序,这里用的是 string 类型(char数组是无法用 sort 函数直接排序的)。
对于 h 和 kh 等价,我们可以找到字符串中的 h,把 h 之前连续的 k 都去掉。而对于 u 和 oo 等价,因为 ooo 有 2 种情况与之等价,所以我们考虑把字符串中所有的 u 换成 oo。
排序的时候可以用 s<t 直接比较 string 类型的字符串 s 和 t 的大小。用 s != t 判断是否不等。
PS:
1.在替换的时候无法直接对 s[i]=t[j] 复制字符……我也不知道为什么……所以只好先用 char 数组修改,在排序之前再转成 string 类型。(又从网上看了下大神的代码,也可以直接用string,见代码 two)
2.将 kkkkkkkh 中 h 之前连续的 k 去除的时候,我的方法是将 k 变为空格。
代码:
one:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int cmp(string a,string b)
{ //比较字符串大小
return a<b;
}
int main()
{
int i,j,k,n,len,tol;
char t[42],s[404][42];
string str[404];
while(cin>>n)
{
for(i=0;i<n;i++)
{
cin>>t;
len=strlen(t);
for(j=1;j<len;j++)
{
if(t[j]=='h')
{ //去除 h 前面连续的 k
k=j-1;
while(k>=0&&t[k]=='k') t[k--]=' '; //换成空格
}
}
tol=0;
for(j=0;j<len;j++)
if(t[j]!=' ')
{ //将 t 存储到 s[i]
if(t[j]=='u')
{ //如果是 u 则换为 oo
s[i][tol++]='o';
s[i][tol++]='o';
}
else s[i][tol++]=t[j];
}
s[i][tol]='\0'; //结束标志
}
for(i=0;i<n;i++) //将 char数组转换成 string类型
str[i]=s[i];
sort(str,str+n,cmp); //排序
//cout<<endl;
//for(i=0;i<n;i++) cout<<str[i]<<endl;
int ans=1;
for(i=1;i<n;i++) //如果相邻字符串不同,则结果+1
if(str[i]!=str[i-1])
ans++;
cout<<ans<<endl;
}
return 0;
}
two:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int cmp(string a,string b)
{ //比较字符串大小
return a<b;
}
int main()
{
int i,j,k,n,len;
string t,s[404];
while(cin>>n)
{
for(i=0;i<n;i++)
{
cin>>t;
len=t.length();
for(j=1;j<len;j++)
{
if(t[j]=='h')
{ //去除 h 前面连续的 k
k=j-1;
while(k>=0&&t[k]=='k') t[k--]=' '; //换成空格
}
}
s[i]="";
for(j=0;j<len;j++)
if(t[j]!=' ')
{ //将 t 存储到 s[i]
if(t[j]=='u') s[i]+="oo"; //如果是 u 则换为 oo
else s[i]+=t[j];
}
s[i]+='\0'; //结束标志
}
sort(s,s+n,cmp); //排序
int ans=1;
for(i=1;i<n;i++) //如果相邻字符串不同,则结果+1
if(s[i]!=s[i-1])
ans++;
cout<<ans<<endl;
}
return 0;
}