題目
我們規定對一個字符串的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;
}