Problem Description
给你一个文本,文本以#结束
问你出现最多的词组是什么,词组定义:连续的两个单词中间只有空格,组合成的就叫做词组
例:above,all ,above all good at good
词组有 above all, all good, good at, at good
问你文本中出现最多的词组是那个,还有出现的次数,如果次数一样按照字典序最小的输出,没注意到这个条件,比赛没有AC,比赛后一改字典序就A了。
思路:
这道题核心点就是把所有的词组提取出来。接下来各种姿势的统计方法都有,我用的字典树,第一反应想到这个,就用了这个。
#include<bits/stdc++.h>
using namespace std;
struct node
{
int data;
node *next[27];//因为有空格,所以26个字母+空格 = 27, 0-25代表'a'-'z',26代表空格
};
int top, ans;
node a[30000];//静态内存
char s[1000], phr[1000], Ans[1000];
node *creat()//初始化
{
node *root = &a[top++];//静态申请内存
root->data = 0;
for(int i = 0; i < 27; i++)
root->next[i] = NULL;
return root;
}
node *Insert(node *root, char str[])
{
node *p = root;
for(int i = 0; str[i]; i++)
{
int t;
if(str[i] == ' ') t = 26;//空格
else
t = str[i] - 'a';//字母
if(!p->next[t]) p->next[t] = creat();
p = p->next[t];
}
p->data++;
if(ans < p->data || (ans == p->data && strcmp(Ans, str) > 0))//找出现次数最多,字典序最小的
{
ans = p->data;
strcpy(Ans, str);
}
return root;
}
int main()
{
top = ans = 0;//初始化
node *root = creat();
int fflag = 0;
while(gets(s))
{
if(s[0] == '#' && !fflag)//我以为#有多行,所以WA的,改了发现还是WA,后面发现是自己没有注意到字典序的问题。
{
printf("%s:%d\n", Ans, ans);//输出
top = ans = 0;//初始化
root = creat();
continue;
}
fflag = 0;
int len = strlen(s);
int cnt = 0, flag = 0, i, j;
for(i = 0; i < len; i++)
{
if((s[i] == ' ' || s[i] == ',' || s[i] == '.') && !flag)//往前找第一个词组
{
int kk = 0, flag1 = 0;
for(j = i-1; j >= 0; j--)
{
if(s[j] == ',' || s[j] == '.' || (flag1 && s[j] == ' ')) break;
if(s[j] == ' ' && !kk)
phr[cnt++] = s[j];
else if(s[j] != ' ')
phr[cnt++] = s[j];
if(s[j] == ' ') kk++;
if(kk && s[j] >= 'a' && s[j] <= 'z') flag1 = 1;
}
if(flag1)
{
phr[cnt] = '\0';
reverse(phr, phr+cnt);
root = Insert(root, phr);//将找到的词组 插入字典树
}
cnt = 0;
flag = 1;
}
else flag = 0;
if(i == len - 1 && !flag) {
s[i+1] = ' ';
len++;
}
}
}
return 0;
}