鄙人才疏学浅,此中鄙陋甚多,望海涵!
题目描述
给定两个字符串a和b,我们定义a*b为他们的连接。
例如,如果a=”abc” 而b=”def”, 则a*b=”abcdef”。
如果我们将连接考虑成乘法,一个非负整数的乘方将用一种通常的方式定义:a0=””(空字符串),a(n+1)=a∗(an)。
输入格式
输入包含多组测试样例,每组测试样例占一行。
每组样例包含一个字符串s,s的长度不超过100。
最后的测试样例后面将是一个点号作为一行。
输出格式
对于每一个s,你需要输出最大的n,使得存在一个字符串a,让s=an。
样例
输入样例:
abcd
aaaa
ababab
.
输出样例:
1
4
3
算法1
STL
C++ 代码
#include<iostream>
using namespace std;
int main()
{
string s;
while(cin>>s,s!=".")
{
for(int i=s.size();i;i--)
{
if(s.size()%i==0)
{
string str,a;
int m=s.size()/i;
str+=s.substr(0,m);
for(int j=0;j<i;j++)
a+=str;
if(a==s)
{
cout<< i <<endl;
break;
}
}
}
}
return 0;
}
算法2
KMP求最小循环节
C++ 代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=110;
int ne[N];
int n;
int main()
{
char s[N];
while(cin>>s+1 && s[1]!='.')
{
int n=strlen(s+1);
for(int i=2,j=0;i<=n;i++)
{
while(j && s[i]!=s[j+1]) j=ne[j];
if(s[i]==s[j+1]) j++;
ne[i]=j;
}
cout<< n/(n-ne[n]) <<endl;
}
return 0;
}
请问您第一个STL写法中怎么判断输出的i为最大,s.size()=16时i=8、i=16、i=4都可以符合这个输出吧
这里是倒着枚举的。
ovo,感谢,懂了
感觉kmp有问题呀,虽然能ac,但是下面这两个数据就过不了。
kmp里面最后那个没看懂cout<< n/(n-ne[n]) <<endl;
n - ne[n] 就是最大循环节的长度
KMP的就看不懂惹
多学学算法,像这种题以后就没人模拟了,而且数据范围肯定不允许暴力的。
嗯嗯,多谢多谢
KMP算法可能对于基础阶段有点早了,下面这个看不懂其实可以掠过;
也可简单解释一下:关键是理解ne这个数组其实是next表;这个表示示如果出错,则下一次比较字符串元素跳过的距离。
以及其实这里的next表其实还可以再优化以应对特殊情况,闲着无聊可以思考一下orz
stl为什么去掉a+=str然后j小于等于i
因为i是重复子串出现的次数,重复出现i次子拼接起来如果等于原串就匹配了
include [HTML_REMOVED]
include [HTML_REMOVED]
using namespace std;
int main()
{
string s;
while(getline(cin,s),s != “.”)
{
string a;
int len = s.size();
for(int i = 1; i <= len; i) // 从字符串a长度为1开始遍历
if(len%i == 0)
{
a = s.substr(0,i);
for(int j = 1; j < len/i; j) // 根据子串a构造, j为a重复的次数
a += a;
if(s == a)
{
cout << len/i << endl;
break;
}
}
}
return 0;
}
xdm帮我看看为什么会Memory Limit Exceeded?
别写a+=a再重新定义一个string变量,for循环,加起来;至于为什么我也不懂,有知道的大佬,可以提点一下;
string temp;
temp+=a;
for(int i=s.size();i;i–) 最小的a是s的一半长把 比如ababab 不可能我找长度4的a把
s.size()/2可以省时间我觉得 你看有错没
可以,但你还需要特判1的
ok 谢谢
客气