1 条题解

  • 0
    @ 2026-5-7 10:56:06

    题目传送门

    提供一个好想的思路( ̄︶ ̄*))。

    思路

    首先两个字符串 S,TS,T 同构当且仅当其可以被表示为 S=s+t,T=t+sS=s+t,T=t+ss,ts,t 均为字符串,++ 表示字符串拼接),不妨把两个字符串拼接起来,最终得到的串一定形如 ...st...ts.....st...ts..,对每个起始位置 ii 跑两遍 KMP 求出 s,ts,t,求出最大的 s+t|s|+|t| 即可,至于翻转的情况,直接将 SS 翻转一下与 TT 拼接成一个新的字符串跑上面的算法即可。

    时间复杂度 O(n2)\mathcal O(n^2),空间复杂度 O(n)\mathcal O(n)

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    const int Maxn=6010;
    int kmp[Maxn],kmp1[Maxn],id[Maxn];
    
    int n,m;
    char S[Maxn],T[Maxn],oth[Maxn],U[Maxn],V[Maxn];
    int ret,bgn,bgm;
    
    inline void solve(int t){
    	int len=n+m;
    	for(int i=1;i<=n;i++){
    		int p1=0,p2=0,tot=0;
    		for(int j=1;j<=len;j++) kmp[j]=0,kmp1[j]=0;
    		for(int j=i;j<=len;j++) U[j-i+1]=oth[j];
    		for(int j=i-1;j;j--) V[++tot]=oth[j],id[tot]=j;
    		for(int j=len;j>=i;j--) V[++tot]=oth[j],id[tot]=j;
    		for(int j=i+1;j<=len;j++){
    			while(p1 and U[p1+1]!=oth[j]) p1=kmp[p1+i-1];
    			if(U[p1+1]==oth[j]) ++p1;
    			kmp[j]=p1;
    		}
    		for(int j=2;j<=tot;j++){
    			while(p2 and V[p2+1]!=V[j]) p2=kmp1[id[p2]];
    			if(V[p2+1]==V[j]) ++p2;
    			kmp1[id[j]]=p2;
    		}
    		for(int j=n+1;j<=len;j++){
    			int mx1=min(min(n-i+1,j-n),kmp[j]);
    			int mx2=min(min(i-1,len-j),kmp1[j+1]);
    			if(mx1+mx2>ret){
    				ret=mx1+mx2;
    				if(t) bgn=n-(i+mx1-1)+1,bgm=j-n-mx1+1;
    				else bgn=i-mx2,bgm=j-n-mx1+1;
    			}
    		}
    	}
    }
    
    int main(){
    	scanf("%s%s",S+1,T+1);
    	n=strlen(S+1),m=strlen(T+1);
    	
    	for(int i=1;i<=n;i++) oth[i]=S[i];
    	for(int i=1;i<=m;i++) oth[i+n]=T[i];
    	solve(0);
    	for(int i=1;i<=n;i++) oth[i]=S[n-i+1];
    	solve(1);
    	
    	printf("%d\n%d %d",ret,bgn-1,bgm-1);
    
    	return 0;
    }
    
    • 1

    信息

    ID
    10581
    时间
    1500ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    3
    已通过
    1
    上传者