P1308 [NOIP2011 普及组] 统计单词数
个人解题思路:
问题一:如何不区分大小写地遍历
解决方案:使用transform函数来转换为小写形式。
transform(s1.begin(),s1.end(),s1.begin(),::tolower);
transform(s2.begin(),s2.end(),s2.begin(),::tolower);
问题二:找出第一次出现的位置和出现位置。
解决方案:使用find函数,匹配上之后判断是否是单词。如果只是单词的一部分,则往后继续搜索,直到正确匹配,第一次匹配特判记录位置。然后不断后移计数。
while((ans=s2.find(s1,ans+len))!=string::npos)
{
if(ans==0&&s2[ans+len]==' '||s2[ans-1]==' '&&s2[ans+len]==' ')
{
if(cnt==0)
pos=ans;
cnt++;
}
}
此段代码可以用于单词的匹配,但是时间复杂度可能较高
洛谷题解启示
- 自动机的概念
那么这是一道简单的有穷自动机,运行时分两种情况:
①是空格
②是字母
(其实当前状态就是上一个字符的状态)那么在遍历数组的时候拿一个变量记录下来当前是什么状态,可以用0代表当前是空格状态,1代表是字母状态
当如果当前状态是1,而现在却遇到空格,那么就计数器加一,同时要将状态改为0,如果当前状态是00,现在的字符却是字母,就只将状态改为1
for(i = 0; a[i]; i ++ ) {//遍历数组
switch ( state ) {
case SPACE : //如果当前状态(上一个)是空格
if(a[i] == word[0]) state = WORD;//变成单词第一个字母状态
else if(a[i] == ' ') state = SPACE;//其实这句话可以省略,因为反正都是空格状态,改它是一样的
else state = LETTER;//剩下的肯定是其他字母状态了
break;
case LETTER : //是其他字母状态
if(a[i] == ' ') state = SPACE;//空格状态
break;
default: //是要查找的单词状态
if ( state < len ) {//还不是最后一个字母
if(a[i] == ' ') state = SPACE;
else if(a[i] == word[state]) state ++ ;//变成下一个字母状态
else state = LETTER;//其他字母状态
}
else if (state == len )//是最后一个字母
{
if(a[i] == ' ') {//如果下一个是空格,找到了!
state = SPACE;//状态不要忘记改变
if(ans2 == -1)//第一次找到,记录下来位置
ans2 = i - len;//因为i是单词的尾,所以要减长度
ans ++ ;//个数加一
}
else state = LETTER;//可惜,最后跟着其他字母,不是单词
}
}
}
源自wxy_god
不断地遍历数组,每次记录状态,根据不同状态进行分类进行下一步运算,时间复杂度低。