题目
我们规定对一个字符串的shift操作如下:
shift(“ABCD”, 0) = “ABCD”
shift(“ABCD”, 1) = “BCDA”
shift(“ABCD”, 2) = “CDAB”
换言之, 我们把最左侧的N个字符剪切下来, 按序附加到了右侧。
给定一个长度为n的字符串,我们规定最多可以进行n次向左的循环shift操作。如果shift(string, x) = string (0<= x <n), 我们称其为一次匹配(match)。求在shift过程中出现匹配的次数。
输入
输入仅包括一个给定的字符串,只包含大小写字符。
样例输入
byebyebye
输出
输出仅包括一行,即所求的匹配次数。
样例输出
3
时间限制
C/C++语言:1000MS其它语言:3000MS
内存限制
C/C++语言:65536KB其它语言:589824KB
完整代码
暴力
运行结果:超时
ac40%
#include<bits/stdc++.h>
using namespace std;
string shift(string str, int n){
string res = "";
res = str.substr(n, str.length() - n) + str.substr(0, n);
return res;
}
int main(){
string str = "";
cin >> str;
int res = 0;
for(int i = 0; i < str.length(); ++i){
if(str == shift(str, i))
++res;
}
cout << res;
return 0;
}
暴力优化
- 如果数组中每个字符都相同,则直接输出长度
- 移动时,移动的长度是总长度的因数时才移动
- 结果:ac:60%,总是显示测试用例:zzzz时出错,但程序在输入:zzzzz,结果就是5啊!!!
#include<bits/stdc++.h>
using namespace std;
string shift(string str, int n){
string res = "";
res = str.substr(n, str.length() - n) + str.substr(0, n);
return res;
}
int main(){
string str = "";
cin >> str;
int j = 1;
while(j < str.length()){
if(str[j] == str[j - 1])
++j;
else
break;
}
if(j == str.length()){
cout << j;
return 0;
}
int res = 0;
for(int i = 0; i < str.length(); ++i){
if(str.length() % (i + 1))
continue;
if(str == shift(str, i))
++res;
}
cout << res;
return 0;
}
借助KMP算法
KMP
- 相当于求字符串的周期,最终长度除以周期就是结果
- 利用s.length() - next[s.length()]就是周期
ac了
#include<bits/stdc++.h>
using namespace std;
int GetNext(string s){
vector<int> next(s.length() + 1);//注意和KMP的区别
next[0] = -1;
int k = -1, j = 0;
while(j < s.length()){
if(k == -1 || s[k] == s[j]){//KMP的next数组未优化形式
++k;
++j;
next[j] = k;
}
else{
k = next[k];
}
}
return next[s.length()];
}
int main(){
string s;
cin >> s;
if(s.length() == 0){
cout << 0;
return 0;
}
int t = s.length() - ((GetNext(s)));
if(s.length() % t == 0)
cout << s.length() / t ;
else
cout << 1;
return 0;
}