字符串环
题目链接:ybt高效进阶2-1-4
题目大意
就是有两个字符串环,问你最长连续公共子串的长度。
思路
这道题主要就是环的问题。
那我们就把环破开,具体方法就是再复制一遍。
(注意,最大的长度还是原来字符串的最小的那一个)
然后首先看公共子串的长度(应该是可以枚举,但是我这里用了二分),然后枚举两个序列是选取哪两段,然后配对。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int an, bn, l, r, ans, mid;
char a[601], b[601];
bool yes;
bool ch(int mid) {
if (mid == 0) return 1;
for (int i = mid; i <= bn; i++) {
//b序列选 i-mid+1~i 这一段
for (int j = mid; j <= an; j++) {
//a序列选 j-mid+1~j 这一段
yes = 1;
for (int k = 0; k < mid; k++)//逐位判断是否相同
if (b[i - k] != a[j - k]) {
yes = 0;
break;
}
if (yes) return 1;
}
}
return 0;
}
int main() {
scanf("%s %s", a + 1, b + 1);
an = strlen(a + 1);
bn = strlen(b + 1);
if (bn > an) {
swap(a, b);
swap(an, bn);
}
for (int i = an + 1; i <= 2 * an; i++)//因为是环,就把它复制一遍
a[i] = a[i - an];
an *= 2;
for (int i = bn + 1; i <= 2 * bn; i++)
b[i] = b[i - bn];
bn *= 2;
l = 0;
r = bn / 2;//因为你就算复制了一遍,最大的还是原来的长度
while (l <= r) {
mid = (l + r) >> 1;
if (ch(mid)) {
ans = mid;
l = mid + 1;
}
else r = mid - 1;
}
printf("%d", ans);
return 0;
}