Codeforces 615C

传送门:http://codeforces.com/contest/615/problem/C

渣渣看题解写的,第一次学lcp,在这里再整理下。

 

题意:

  给出两个字符串,每次可以从第一个字符串中截取一部分子串,要求用数目最少的子串拼接成第二个字符串,如果无法拼接,输出-1,否则输出子串的数目以及截取的区间。注意子串可以正序截取,也可以反序截取。

 

解题思路:

  用二维数组 lcp[i][j] 表示 字符串 t 的由 i 到 lt (字符串 t 的长度)的部分与字符串 s 的由 j 到 ls 的部分的最长公共前缀长度。那么计算过程如下:

for(int i=lt;i>0;i--){
    for(int j=ls;j>0;j--) if(t[i]==s[j])
        lcp[i][j]=lcp[i+1][j+1]+1;
}

  因为题目中还可以反序截取,所以需要计算rlcp,同理:

for(int i=lt;i>0;i--){
    for(int j=1;j<=ls;j++) if(t[i]==s[j])
        rlcp[i][j]=rlcp[i+1][j-1]+1;
}

  为了偷懒,rlcp[i][j]的定义有了些许改动:为 t 的由 i 到 lt 部分与 s 的由 1 到 j 部分的最长公共前缀长度。 

  后面的只需要枚举 i ,选取最大值即可。详见代码。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=2110;
char s[N],t[N];
int ls,lt,cnt,lcp[N][N],rlcp[N][N],L[N],R[N];
int main(){
    //freopen("in.txt","r",stdin);
    while(~scanf("%s%s",s+1,t+1)){
        ls=strlen(s+1),lt=strlen(t+1);
        memset(lcp,0,sizeof(lcp));
        memset(rlcp,0,sizeof(rlcp));
        for(int i=lt;i>0;i--){
            for(int j=ls;j>0;j--) if(t[i]==s[j])
                lcp[i][j]=lcp[i+1][j+1]+1;
        }
        for(int i=lt;i>0;i--){
            for(int j=1;j<=ls;j++) if(t[i]==s[j])
                rlcp[i][j]=rlcp[i+1][j-1]+1;
        }
        cnt=0;
        bool use_rev,flag=true;
        for(int i=1,mx=0,nxt;i<=lt;i+=mx){
            mx=0,use_rev=false;
            for(int j=1;j<=ls;j++) if(lcp[i][j]>mx){
                mx=lcp[i][j],nxt=j;
            }
            for(int j=1;j<=ls;j++) if(rlcp[i][j]>mx){
                mx=rlcp[i][j],nxt=j,use_rev=true;
            }
            if(mx==0){
                flag=false;
                break;
            }
            if(use_rev) R[cnt]=nxt-mx+1;
            else R[cnt]=nxt+mx-1;
            L[cnt++]=nxt;
        }
        if(flag){
            printf("%d\n",cnt);
            for(int i=0;i<cnt;i++)
                printf("%d %d\n",L[i],R[i]);
        }
        else puts("-1");
    }
    return 0;
}

 

posted @ 2016-01-19 14:35  轶辰  阅读(257)  评论(0编辑  收藏  举报