您的位置:首页 > 其它

玲珑杯 第4次 String cut(暴力字符串)

2016-11-06 01:04 375 查看

题意:给你长度为n(<=100000)的字符串,问你任意删除一个字符后得到循环节最多的数量是多少

 

题解:最简单的想法就是枚举删除的字符,再kmp求循环节,但是时间复杂度为O(n*n)会超时

因此我们需要这样,需要删除的字符我们不能枚举,只能通过一些特别的方法来寻找或者判断

我们根据kmp求循环节的想法来枚举循环节长度(相当于是答案),因为循环节长度是(n-1)的因子少于log2(n)个

所以我们枚举了循环节的长度后可以使用O(n)来判断长度为m的循环节是否满足条件

此时我们可以这样想:先假设我们需要删除的字符在第一个循环节内,此时我们先找出[0,m]的字符,然后[m+1,2*m]与[0,n]

进行枚举匹配,当不同时就将[0,n]这一个向后跳一个在比较(当然只能跳一次),否则当需要删除的字符在第一个循环节后面,

这样我们[0,m-1]就一定是循环节,这样再与[0,n]枚举匹配判断就好了

 

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=1<<28;
const ll INF=1ll<<60;
const double Pi=acos(-1.0);
const int Mod=1e9+7;
const int Max=1e5-7;
char str[Max];
string tem;
int Jud(int n,int dig,int num)//n长度 dig循环节长度 num循环节个数
{
tem.clear();
for(int i=0; i<dig; ++i)//假设[0,m-1]为循环节
tem+=str[i];
int flag=0;
for(int i=dig; i<n; ++i)
{
if(tem[(i+flag)%dig]!=str[i])//跳
{
if(flag==-1)
{
flag=-2;
break;
}
else
{
flag=-1;
}
}
}
if(flag!=-2)
return 1;
tem.clear();
for(int i=dig+1; i<dig+dig+1; ++i)//[m+1,2*m]为循环节
tem+=str[i];

flag=0;
for(int i=0; i<n; ++i)
{
if(tem[(i+flag)%dig]!=str[i])
{
if(flag==-1)
{
flag=-2;
break;
}
else
{
flag=-1;
}
}
}
if(flag!=-2)
return 1;
return 0;
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
scanf("%s",str);
for(int i=1; i<=n-1; ++i)//枚举循环节长度
{
if(i==n-1||(n-1)%i==0&&Jud(n,i,(n-1)/i))//判断
{
printf("%d\n",(n-1)/i);
break;
}
}
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: