输入一个字符串,输入的只有两种字符,一种是字母,一种是空格。现在求一共有几个单词。注意,有可能有多个空格连在一起,开头和结尾都有可能有空格。
有穷自动机的意思是,有多种状态同时进行
那么这是一道简单的有穷自动机,运行时分两种情况:
①是空格
②是字母
(其实当前状态就是上一个字符的状态
那么在遍历数组的时候拿一个变量记录下来当前是什么状态,可以用000代表当前是空格状态,111代表是字母状态
当如果当前状态是111,而现在却遇到空格,那么就计数器加一,同时要将状态改为000,如果当前状态是000,现在的字符却是字母,就只将状态改为111
不过要注意
在跳出循环的时候如果状态是111,要将计数器加一,否则如果最后是字母就会少统计一个单词!
(所以可以在最后人为加几个空格)
1 #include <cstdio> 2 3 int main () { 4 5 char a[1001]; 6 int state, ans = 0; 7 8 gets(a); 9 10 if(a[0] == ' ') state = 0;//设置初始值 11 else state = 1; 12 13 for(int i = 1; a[i]; i ++ ) {//要从一开始遍历,因为零已经遍历过了 14 if(a[i] == ' ') {//是空格 15 if(state == 1) {//当前状态(前一个)是字母,说明找到一个单词了 16 ans ++ ;//答案加一 17 state = 0;//千万别忘了改状态 18 } 19 } 20 else {//是字母 21 if(state == 0) {//当前状态(前一个)是空格 22 state = 1;//将状态改为1 23 } 24 } 25 } 26 27 if(state == 1)//最后还要判断一下千万不要忘记 28 ans ++ ; 29 printf("%d", ans); 30 31 return 0; 32 }
判断条件:前一个是字母(state=1)后一个是空格.最后一个如果是字母,则加一.
P1308 洛谷
1 #include <cstdio> 2 3 int main () { 4 5 char a[1001]; 6 int state, ans = 0; 7 8 gets(a); 9 10 if(a[0] == ' ') state = 0;//设置初始值 11 else state = 1; 12 13 for(int i = 1; a[i]; i ++ ) {//要从一开始遍历,因为零已经遍历过了 14 if(a[i] == ' ') {//是空格 15 if(state == 1) {//当前状态(前一个)是字母,说明找到一个单词了 16 ans ++ ;//答案加一 17 state = 0;//千万别忘了改状态 18 } 19 } 20 else {//是字母 21 if(state == 0) {//当前状态(前一个)是空格 22 state = 1;//将状态改为1 23 } 24 } 25 } 26 27 if(state == 1)//最后还要判断一下千万不要忘记 28 ans ++ ; 29 printf("%d", ans); 30 31 return 0; 32 } 33 34 那么,这就是简单的自动机代码,现在看看本题用自动机如何做 35 36 其实一样,就是注意字母状态分时要查找单词状态和不是要查找单词状态,而且单词第nnn个字母的状态就用nnn来表示 37 38 以下是code: 39 40 #include <cstdio> 41 #include <cctype> 42 #include <cstring> 43 44 const int SPACE = 0;//三种状态,这是空格状态 45 const int LETTER = -1;//字母状态,但这表示不是要查找的单词的字母的状态 46 const int WORD = 1;//而这种状态是要查找的单词的状态 47 //当然了,如果状态时大于1的数,说明是要查找的单词的中间部分的状态,上文讲过了 48 49 inline void strlower (char *a) {//不解释,上面的代码有了 50 for(int i = 0; a[i]; i ++ ) { 51 if(isupper(a[i])) a[i] = tolower(a[i]); 52 } 53 } 54 55 int main () { 56 57 char a[1000001], word[20]; 58 int ans = 0; 59 int ans2 = -1; 60 int state = 0;//表状态,假设是空格,因为空格上来就判断是不是三种状态 61 int i; 62 63 gets(word); 64 gets(a); 65 strlower(a); 66 strlower(word); 67 int len = strlen( word ); 68 69 for(i = 0; a[i]; i ++ ) {//遍历数组 70 switch ( state ) { 71 case SPACE : //如果当前状态(上一个)是空格 72 if(a[i] == word[0]) state = WORD;//变成单词第一个字母状态 73 else if(a[i] == ' ') state = SPACE;//其实这句话可以省略,因为反正都是空格状态,改它是一样的 74 else state = LETTER;//剩下的肯定是其他字母状态了 75 break; 76 case LETTER : //是其他字母状态 77 if(a[i] == ' ') state = SPACE;//空格状态 78 break; 79 default: //是要查找的单词状态 80 if ( state < len ) {//还不是最后一个字母 81 if(a[i] == ' ') state = SPACE; 82 else if(a[i] == word[state]) state ++ ;//变成下一个字母状态 83 else state = LETTER;//其他字母状态 84 } 85 else if (state == len )//是最后一个字母 86 { 87 if(a[i] == ' ') {//如果下一个是空格,找到了! 88 state = SPACE;//状态不要忘记改变 89 if(ans2 == -1)//第一次找到,记录下来位置 90 ans2 = i - len;//因为i是单词的尾,所以要减长度 91 ans ++ ;//个数加一 92 } 93 else state = LETTER;//可惜,最后跟着其他字母,不是单词 94 } 95 } 96 97 } 98 99 if(state == len) { 100 ans ++ ; 101 if(ans2 == -1) 102 ans2 = i - 1 - len; 103 } 104 if(ans2 == -1) printf("-1"); 105 else printf("%d %d", ans, ans2); 106 107 return 0; 108 }
(转载自AH是女孩子 的题解)