转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题目:有两个串,s,f f(s, i, j) = s[i + 1... j - 1] + r(s[j... n - 1]) + r(s[0... i]).
通过二元组(i,j)对原串s进行变换,得到新的串,现在要你求这个二元组
http://codeforces.com/problemset/problem/119/D 
 
哈哈,爽,终于A了
第一次在CF上调试这么艰辛,TLE+WA刷了好多
我们将两个串表示成a,b,分为三个部分
a ( 1 , 2 , 3 ) a'表示a的反序
那么b ( 2 , 3' , 1' ) b'表示b的反序
我的做法是,第一步,枚举i,首先我们可以看到a和b‘的最长公共前缀。
由于 题目要求i最大,所以先求出a和b'的最长公共前缀长度,mx+1
然后i便可以从mx可能枚举。
接下来相当于枚举j,但是直接枚举肯定会TLE
可以发现b的后缀除了1'之后,便是a’的前缀。
那么我们用a'和b做一次KMP,记录对于b中的某个位置,能匹配的最远距离pos[]
但是并不一定j越远就好,所以枚举的时候,从pos[]出发,通过next[]数组就能枚举到可能的j
这样枚举出来的,肯定是满足1,3这两个部分
剩下的就是判断两个串的剩下部分也就是部分2是否匹配了。这一部分通过HASH就能O(1)处理。
但是这样还是会TLE,因为可以知道像aaaaaaaaaaabaaaaaaaaa这种串,通过next数组转移很慢的。还是相当于枚举
这里我又加了个优化,用b串和a串直接跑一次KMP,记录对于a中的某个位置,和b的前缀最长能匹配的长度dp[]。
那么在枚举i之后,枚举j,通过这个长度 能作一次剪枝
但是这里又WA了很久。这是因为在处理dp[]数组的时候,我只是在向前移动匹配的时候,转移了dp[]数组,其实是不对的。即使不能匹配,通过next[]数组,也是能得到后缀的前缀和前缀是匹配的,也是可以转移的。
以上想法,纯属是自己不成熟的做法,而且也表述不清
欢迎交流。可以看下代码
#include<iostream>  
#include<cstdio>  
#include<map>  
#include<cstring>  
#include<cmath>  
#include<vector>  
#include<algorithm>  
#include<set>  
#include<string>  
#include<queue>  
#define inf 1600005  
#define M 40  
#define N 1000005
#define maxn 300005  
#define eps 1e-12
#define zero(a) fabs(a)<eps  
#define Min(a,b) ((a)<(b)?(a):(b))  
#define Max(a,b) ((a)>(b)?(a):(b))  
#define pb(a) push_back(a)  
#define mp(a,b) make_pair(a,b)  
#define mem(a,b) memset(a,b,sizeof(a))  
#define LL long long  
#define MOD 1000000007
#define lson step<<1
#define rson step<<1|1
#define sqr(a) ((a)*(a))  
#define Key_value ch[ch[root][1]][0]  
#define test puts("OK");  
#define pi acos(-1.0)
#define lowbit(x) ((-(x))&(x))
#define HASH1 1331
#define HASH2 10001
#pragma comment(linker, "/STACK:1024000000,1024000000")  
using namespace std;
char a[N],a_2[N],b[N];
int la,lb;
int next[N];
int pos[N];
int dp[N];
LL fac1[N]={1},fac2[N]={1};
LL h11[N]={0},h21[N]={0};
LL h12[N]={0},h22[N]={0};
void get_next(char *s,int len){
    next[0]=-1;
    int i=0,j=-1;
    while(i<len){
        if(j==-1||s[i]==s[j]){
            i++;j++;
            next[i]=j;
        }
        else j=next[j];
    }
}
void match(char *pat,int lp,char *str,int ls,int flag){
    int i=0,j=0;
    while(i<lp&&j<ls){
        if(i==-1||pat[i]==str[j]){
            if(!flag) pos[j]=i;
            if(flag&&i!=-1){
                dp[j-i]=max(dp[j-i],i+1);
            }
            i++;j++;
        }
        else{
            i=next[i];
            dp[j-i]=max(dp[j-i],i+1);
        }
        if(i==lp) i=next[i];
    }
}
LL get(int l,int r,LL *hash,LL *fac){
    l++;r++;
    return hash[r]-hash[l-1]*fac[r-l+1];
}
int main(){
    //freopen("input.txt","r",stdin);
    for(int i=1;i<N;i++){
        fac1[i]=fac1[i-1]*HASH1;
        fac2[i]=fac2[i-1]*HASH2;
    }
    while(gets(a)!=NULL&&gets(b)!=NULL){
        la=strlen(a);lb=strlen(b);
        if(la!=lb){
            //if(a[0]==a[1]&&a[2]==a[3]&&a[2]==' ') cout<<3333333333<<endl;
            printf("-1 -1\n");
            continue;
        }
        for(int i=0;i<la;i++)
            a_2[i]=a[la-i-1];
        for(int i=1;i<=la;i++){
            h11[i]=h11[i-1]*HASH1+a[i-1];
            h12[i]=h12[i-1]*HASH2+a[i-1];
        }
        for(int i=1;i<=lb;i++){
            h21[i]=h21[i-1]*HASH1+b[i-1];
            h22[i]=h22[i-1]*HASH2+b[i-1];
        }
        get_next(a_2,la);
        match(a_2,la,b,lb,0);
        mem(dp,-1);
        get_next(b,lb);
        match(b,lb,a,la,1);
        int l=-1,r=-1,mx=-1;
        for(int i=0;i<la;i++)
            if(a[i]==b[lb-i-1]){
                mx=i;
            }
            else break;
        for(int i=min(la-2,mx);i>=0;i--){
            int p=pos[lb-i-2];
            while(p>=0){
                int j=la-p-1;
                if(j-i-1>dp[i+1]&&j-i-1!=0) break;
                if(i+1==j){
                    l=i,r=j;
                }
                else{
                    LL t1=get(i+1,j-1,h11,fac1),t2=get(0,j-i-2,h21,fac1);
                    LL t3=get(i+1,j-1,h12,fac2),t4=get(0,j-i-2,h22,fac2);
                    if(t1==t2&&t3==t4) l=i,r=j;
                }
                p=next[p];
                if(l!=-1) break;
            }
            if(l!=-1) break;
        }
        printf("%d %d\n",l,r);
    }
    return 0;
}
 
 
 
 
 
                   
                   
                   
                   
                            
 
                             本文提供了一种解决CodeForces D题的有效方法,通过KMP算法和Hash技巧来优化匹配过程,确保找到最佳的字符串变换方案。
本文提供了一种解决CodeForces D题的有效方法,通过KMP算法和Hash技巧来优化匹配过程,确保找到最佳的字符串变换方案。
           
       
           
                 
                 
                 
                 
                 
                
               
                 
                 
                 
                 
                
               
                 
                 扫一扫
扫一扫
                     
              
             
                   2528
					2528
					
 被折叠的  条评论
		 为什么被折叠?
被折叠的  条评论
		 为什么被折叠?
		 
		  到【灌水乐园】发言
到【灌水乐园】发言                                
		 
		 
    
   
    
   
             
            


 
            