OpenJudge NOI 1.13 26:n-gram串频统计

【题目链接】

OpenJudge NOI 1.13 26:n-gram串频统计

【题目考点】

1. 字符串
2. 顺序查找
3. STL map

【解题思路】

解法1:数组中顺序查找

设string类对象数组w,w[i]表示第i个子串。设计数数组ct,ct[i]表示第i个子串出现的个数。
遍历输出的字符串,取出每个长为n的子串t。在数组w中顺序查找是否存在t:

  • 如果存在t,那么该子串出现的次数加1。
  • 如果不存在t,那么在w数组中添加子串t,出现的次数为1。

在构造好w与ct后,求ct中的最大值mx。mx即为子串出现的最高频度。
如果mx小于等于1,就要输出NO。否则,遍历ct,输出其中频度等于mx的子串。

解法2:使用STL map

map可以用来保存键值对,本题中键是子串,值是子串出现的频度。
先枚举原字符串中所有长为n的子串,统计出每个子串出现的频度,保存在map<string, int> mp之中,mp[sub]就是子串sub出现的频度。
而后遍历mp,找到子串出现的最大频度mx。
如果mx小于等于1,输出NO。
否则从前向后枚举所有原字符串的长为n的子串,如果该子串的频度为mx,则输出该子串,而后把该子串的频度改为0,使得下一次枚举到该子串时不输出该子串。

【题解代码】

解法1:数组中顺序查找
#include<bits/stdc++.h>
using namespace std;
#define N 505
string s, w[N], t;//w[i]:第i个子串 
int n, wi, ct[N], mx;//ct[i]:第i个子串出现的次数 mx:最高频度 
int main()
{
    cin >> n >> s;
    for(int i = 0; i <= s.length()-n; ++i)//最后一次取到的子串下标为len-n~len-1 
    {
        t = s.substr(i, n);//取到的子串 
        bool isfound = false;
        for(int j = 1; j <= wi; ++j)//顺序查找 
        {
            if(w[j] == t)
            {
                ct[j]++;
                isfound = true;
                break;
            }
        }
        if(isfound == false)//如果没找到,则添加一个子串 
        {  
            w[++wi] = t;
            ct[wi] = 1;
        }
    }
    for(int i = 1; i <= wi; ++i)//求最大的频度 
        mx = max(mx, ct[i]);
    if(mx <= 1)
        cout << "NO";
    else
    {
        cout << mx << endl;//输出最高频度 
        for(int i = 1; i <= wi; ++i)
        {
            if(ct[i] == mx)//输出频度最高的子串 
                cout << w[i] << endl;
        }
    }
    return 0;
}
解法2:使用STL map
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n, mx = 0;//最高频度 
	map<string, int> mp;//mp[子串]:子串个数
	string s, sub;
	cin >> n >> s;
	for(int i = 0; i <= s.length()-n; ++i)
	{
		sub = s.substr(i, n);//子串
		mp[sub]++;//如果不存在键为sub的键值对,会先插入键值对(sub,0),而后让值增加1。 
	} 
	for(pair<string, int> p : mp)
		mx = max(mx, p.second);//求所有键值对中值(子串个数)的最大值 
	if(mx <= 1)
		cout << "NO";
	else
	{
		cout << mx << endl;
		for(int i = 0; i <= s.length()-n; ++i)
		{
			sub = s.substr(i, n);//子串
			if(mp[sub] == mx)//如果子串出现的频度为最大频度 
			{
				cout << sub << endl;
				mp[sub] = 0;//每种子串只输出一次,如果再次取到sub,则不会输出。 
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值