样例:
输入:
2
2 2
ab
ba
1
1 2
4 3
aab
baa
bba
bab
6
1 2
1 3
1 4
2 3
2 4
3 4输出:
Yes
Yes
No
No
No
No
Yes
题目大意:
给定一个字符串数组,每次查询两个字符串是否可以通过一个字符串循环右移可以变成另一个字符串,循环右移定义如下:
aabbccds经过一次循环右移变成saabbccd,在经过一次就变成了dsaabbcc;
思路:
这个题首先我们想到的肯定预处理出来某些东西,后面查询时间直接比较就行。我们如果想要通过字符串右移使用substr分割,找出最小的来,或者把他的可能全部存下来,后面在进行字符串的比较,这样很显然时间复杂度太高了。因为每一个substr的时间复杂度是O(n),字符串比较的时间复杂度也是O(n),
所以我们优化一下,首先就是想,我们有没有什么算法可以比较快的找出最小的右移字符串。所以就找到了我们的板子,找循环串的最小表示。这个时间复杂度是O(s.size()),而substr的复杂度是O(n * s.size() * s.size() ),时间复杂度一下子降下来很多。
循环串的最小表示的板子:
string zuixiao(string s) { int i, j ,k ,l; int N = s.length(); s += s; for (i=0, j=1; j<N;) { for (k=0; k<N && s[i+k] == s[j+k]; k++) ; if (k >=N ){ break; } if (s[i+k] <s[j+k]) { j += k+1; } else { l = i + k; i = j; j = max(l ,j) + 1; } } return s.substr(i, N); }
其次我们可以在想,预处理的时间复杂度降下来了,但是后面比较时间的时间复杂度还没有降下来,每次两个字符串比较的复杂度是O(s.size() ) ,所以我们就需要在优化一下,既然不能用字符串比较,那我们就可以考虑怎么能转化成O(1),我们会想到数的比较可以实现,所以我们就想到了字符串哈希,用字符串哈希可以搞定。
字符串哈希的知识点 (我队友写的)
字符串哈希计算的板子:
ull jshx(string s){ int len = s.size(); for(int i = 1;i <= len;i++){ h[i] = h[i - 1] * haxishu + s[i]; } return h[len]; }
这个题的AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
string s[N];
typedef unsigned long long ull;
const ull haxishu = 131;
ull h[N];
ull sshh[N];
string zuixiao(string s) {
int i, j ,k ,l;
int N = s.length();
s += s;
for (i=0, j=1; j<N;) {
for (k=0; k<N && s[i+k] == s[j+k]; k++) ;
if (k >=N ){
break;
}
if (s[i+k] <s[j+k]) {
j += k+1;
} else {
l = i + k;
i = j;
j = max(l ,j) + 1;
}
}
return s.substr(i, N);
}
void init(){
h[0] = 1;
for(int i = 1;i <= 1e5;i++){
h[i] = h[i - 1] * haxishu;
}
}
ull jshx(string s){
int len = s.size();
for(int i = 1;i <= len;i++){
h[i] = h[i - 1] * haxishu + s[i];
}
return h[len];
}
void solve(){
int n,m;
h[0] = 1;
cin >> n >> m;
for(int i = 1;i <= n;i++){
string s1;
cin >> s1;
s[i] = " " + s1;
sshh[i] = jshx(zuixiao(s1));
}
int q;
cin >> q;
// cout << q;
while(q--){
int x,y;
cin >> x >> y;
if(sshh[x] == sshh[y]){
cout << "Yes\n";
}
else cout << "No\n";
}
}
int main()
{
int T;
cin >> T;
while(T--){
solve();
}
}