蓝桥杯--算法训练 字串统计

问题描述
  给定一个长度为n的字符串S,还有一个数字L,统计长度大于等于L的出现次数最多的子串(不同的出现可以相交),如果有多个,输出最长的,如果仍然有多个,输出第一次出现最早的。
输入格式
  第一行一个数字L。
  第二行是字符串S。
  L大于0,且不超过S的长度。
输出格式
  一行,题目要求的字符串。

  输入样例1:
  4
  bbaabbaaaaa

  输出样例1:
  bbaa

  输入样例2:
  2
  bbaabbaaaaa

  输出样例2:
  aa
数据规模和约定
  n<=60
  S中所有字符都是小写英文字母。

  提示
  枚举所有可能的子串,统计出现次数,找出符合条件的那个
注意;题目的要求;1,出现次数最多的。2,若出现次数一样多,则输出长度最长的。3,若长度一样长则输出,出现最早的字符串。
题目要点:枚举所有可能的字符串时,条件的控制,
本题为for(int i=0;i<len;i++)
              for(int j=i+n-1;j<len;j++)
这两重循环,字符匹配时使用的kMp算法。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
void next(char t[],int next[])
{
	int i=0,j=-1;
	next[0]=-1;
	int lent=strlen(t);
	while(i<lent)
	{
		if(j==-1||t[i]==t[j])
		{
			i++;
			j++;
			next[i]=j;
		}
		else
		j=next[j];
	}
	
}
int kmp(char s[],char t[])
{
	int i=0,j=0;
	int lens=strlen(s);
	int lent=strlen(t);
	int t1=0;
	int nex[70];
	next(t,nex);
	while(i<lens)
	{
		if(j==-1||s[i]==t[j])
		{
			i++;
			j++;
		}
		else
		  j=nex[j];
		if(j==lent)
		{
			j=nex[j];
			t1++;
		}
	}
	return t1;
}
int main()
{
	char s1[70];
	char s[70];
    int n;
	cin>>n;
	cin>>s1;
	int max1=-1;
	int len=strlen(s1);
	if(n>0&&n<len)
	{
	strncpy(s,s1,n);
	s[n]='\0';
	int vis=-1;
	for(int i=0;i<len;i++)//枚举出所有长度大于n的子串 
	{
	  for(int j=i+n-1;j<len;j++)
	  {
	  	char str[70];
	  	int t=j-i+1;
	  	strncpy(str,s1+i,t);//取s1串中从第i个字符开始的长度为t的字串给str 
	  	str[j-i+1]='\0';
	  	int temp=kmp(s1,str);//kmp算法求出该字串在主串中出现的次数 
	  	int len1=strlen(str);
	    if(max1<temp)//记录出现次数最多的子串 
	    {
	    	max1=temp;
	    	vis=t;
	    	strcpy(s,str);
	    	
	    }
	    if(max1==temp)//若两串出现的次数一样多,则取最长的。 
	    {
	    	if(vis<t)//用小于来控制,得到的是出现最早的子串 
	    	{
	    		max1=temp;
	    	    strcpy(s,str);
	    	}
	    	
	    }
	  }
	}
	cout<<s<<endl;
    }
	return 0;
	
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值