传送门:题目
题意:
给n个字符串,每个字符串都可以做一个操作:字符串的第一位移到字符串的末尾,剩下的字符向前进一位,问最少做多少次操作,所有字符串能相等。
题解:
第一开始我想到的是纯模拟,模拟字符串向前移动的过程,然后 n2 n 2 搜索最优解,不知不觉写了5个for循环,算了一下复杂度 505=109 50 5 = 10 9 ,心想肯定T了,然后交了一下,看看能不能卡过去,竟然跑了 30ms 30 m s 就AC了,果然数据很水,赛后看题解,发现一种巧妙的办法,就是把字符串×2倍,然后找子串,这样的复杂度是 O(n2+log2n) O ( n 2 + log 2 n ) ,方法很好记录一下。
AC代码:(纯模拟)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;
int cnt = 0, ans = INF, n;
string str[55], ori[55];
void init() {
for (int i = 0; i < n; i++)
str[i] = ori[i];
}
void frontstep1(string& a) {
a += *a.begin();
a.erase(0, 1);
}
bool check(string a, string b) {
return a == b;
}
int main(void) {
cin >> n;
for (int i = 0; i < n; i++)
cin >> str[i], ori[i] = str[i];
for (int i = 0; i < n; i++) {
init();
cnt = 0;
for (int j = 0; j < n; j++) {
if (j == i)
continue;
for (int k = 0; k < 55; k++) {
if(k==54)
return 0 * puts("-1");
if (check(str[j], ori[i]))
break;
frontstep1(str[j]);
cnt++;
}
}
ans=min(ans,cnt);
}
cout<<ans<<endl;
return 0;
}
AC代码:(字符串拼接找子串)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;
int main(void){
int mmin=INF,n,index;
string str[60];
cin>>n;
for(int i=0;i<n;i++)
cin>>str[i];
for(int i=0;i<n;i++){
int sum=0;
for(int j=0;j<n;j++){
index=(str[j]+str[j]).find(str[i]);
index==(int)string::npos?sum=-1:sum+=index;
}
mmin=min(mmin,sum);
}
cout<<mmin<<endl;
return 0;
}