将两个字符环各自复制一遍,在双串上用最长公共子串 DP 求答案。
OJ: noi_openjudge
题目 ID: ch0107-30
难度:普及/提高-
标签:动态规划字符串python
日期: 2026-07-30 23:01
题意
两个字符串首尾相连形成字符环,求两环的最长连续公共字符串长度。
思路
把每个环复制为两倍长度,任意跨越原串末尾的连续片段都会变成双串中的普通子串。设 dp[i][j] 为两个双串分别以第
公共片段不能绕环超过一整圈,因此每个状态取不超过两原串较短长度的值。代码用两行数组滚动保存 DP。
代码
Python代码
python
first, second = input().split()
first_twice = first + first
second_twice = second + second
maximum_length = min(len(first), len(second))
previous = [0] * (len(second_twice) + 1)
answer = 0
for first_character in first_twice:
current = [0] * (len(second_twice) + 1)
for index, second_character in enumerate(second_twice, 1):
if first_character == second_character:
current[index] = min(previous[index - 1] + 1, maximum_length)
answer = max(answer, current[index])
previous = current
print(answer)C++代码
cpp
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s1[1000];
char s2[1000];
char tmp[1000];
int main(){
scanf("%s",s1+1);
scanf("%s",s2+1);
int l1 = strlen(s1+1);
int l2 = strlen(s2+1);
int i,j;
for (i=1;i<l1;i++){
s1[l1+i] = s1[i];
}
for (i=1;i<l2;i++){
s2[l2+i] = s2[i];
}
if(l1 < l2){
swap(s1,s2);
swap(l1,l2);
}
for(i=l2;i>=1;i--){
for(j=1;j<=l2+l2-i;j++){
memset(tmp,0,sizeof(tmp));
strncpy(tmp,s2+j,i);
//printf("%d %s\n",i,tmp);
if( strstr(s1+1,tmp)!=NULL){
//printf("%s",s2+j);
printf("%d",i);
return 0;
}
}
}
printf("0");
return 0;
}复杂度
设两串长度为
总结
环上的连续子串问题常先把环展开成双倍字符串,再套线性字符串算法。