zoukankan      html  css  js  c++  java
  • hdu 4300(kmp)

    题意:说实话这个题的题意还真的挺难懂的,我开始看了好久都没看懂,后来百度了下题意才弄懂了,这题的意思就是首先有一个字母的转换表,就是输入的第一行的字符串,就是'a'转成第一个字母,'b'转成转换表的第二个字母·······然后下面一个字符串是密文+明文的形式的字符串。就是说前后两段是重复的,只不过通过转换表转换了下。而且后面一段可能不完整,让我们补完整。

    思路:这道题我很久之前就已经a掉了,当时是用普通的kmp做的,稍微变通下就行了。只不过现在正在学习扩展kmp,所以就用扩展kmp做了下,个人觉得普通的kmp还好一点,代码短也容易理解。

    我现在讲两种方法:

    第一种、普通的kmp首先题目中输入的字符串:密文+明文,假设该字符串为s1,第一步:把s1全部翻译一遍变成:明文+密文,假设该字符串为s2;第二步:我们以s1的后半段为主串,以s2为模式串进行kmp即可。

    代码实现:

    #include<iostream>
    #include<cstring>
    using namespace std;
    char a[100001],c[100001];
    int next[100001];
    int main()
    {
        int T,i,j,len,nima[27],mid;
        char b[27];
        while(scanf("%d",&T)!=EOF)
        {
            getchar();
            while(T--)
            {
                scanf("%s%s",b+1,a+1);
                for(i=1;i<=26;i++)
                   nima[b[i]-'a']=i-1;
                len=strlen(a+1);
                for(i=1;i<=len;i++)
                    c[i]='a'+nima[a[i]-'a'];
                i=1;j=0;next[1]=0;
                while(i<len)
                {
                    if(j==0||c[i]==c[j])
                    {
                        i++;j++;
                        next[i]=j;
                    }
                    else
                        j=next[j];
                }
                if(len%2==0)
                    i=len/2+1;
                else
                    i=len/2+2;
                j=1;mid=i;
                while(i<=len)
                {
                    if(j==0||a[i]==c[j])
                    {
                        i++;j++;
                        
                    }
                    else
                        j=next[j];
                }
                for(i=1;i<=len;i++)
                    printf("%c",a[i]);
                for(i=j;i<j+len-2*j+2;i++)
                    printf("%c",c[i]);
                printf("
    ");
            }
        }
        return 0;
    }

    第二种、扩展kmp,首先题目中输入的字符串:密文+明文,假设该字符串为s1,第一步:把s1 的后半段翻译译一遍变成:假设该字符串为s2;第二步:以s1为主串,s2为模式串进行一次扩展kmp,得到extend数组;第三步:对extend数组进行一次扫描,如果主串某一位置的后缀与模式串的前缀全部匹配就立即停止,这一位置就是满足的最优解了。

    代码实现:

    #include<stdio.h>
    #include<string.h>
    char str1[26],T[100005];
    char s1[26],S[100005];
    int next[100005],extend[100005];
    void get_next()
    {
        int len=strlen(T),j,a,k,p,L;
        next[0]=len;
        a=0;
        while(a<len-1&&T[a]==T[a+1])
            a++;
        next[1]=a;
        a=1;
        for(k=2;k<len;k++)
        {
            p=a+next[a]-1;
            L=next[k-a];
            if(k+L-1>=p)
            {
                j=p-k+1>0?p-k+1:0;
                while(j+k<len&&T[j+k]==T[j])
                    j++;
                next[k]=j;
                a=k;
            }
            else
                next[k]=L;
        }
    }
    void get_extend()//S为主串,T为模式串
    {
        int len1,len2,len,j,k,a,p,L;
        get_next();
        len1=strlen(S);
        len2=strlen(T);
        len=len1>len2?len2:len1;
        a=0;
        while(a<len&&S[a]==T[a])
            a++;
        extend[0]=a;
        a=0;
        for(k=1;k<len1;k++)
        {
            p=a+extend[a]-1;
            L=next[k-a];
            if(k+L-1>=p)
            {
                j=p-k+1>0?p-k+1:0;
                while(j+k<len1&&j<len2&&S[j+k]==T[j])
                    j++;
                extend[k]=j;
                a=k;
            }
            else
                extend[k]=L;
        }
    }
    int main()
    {
        int t,i,len,mid,max,len1;
        while(scanf("%d",&t)!=EOF)
        {
            getchar();
            while(t--)
            {
                max=-1;
                scanf("%s",str1);
                scanf("%s",T);
                for(i=0;i<26;i++)
                    s1[str1[i]-'a']=i+'a';
                len=strlen(T);
                if(len%2==0)
                    mid=len/2;
                else
                    mid=len/2+1;
                for(i=mid;i<len;i++)
                    S[i-mid]=str1[T[i]-'a'];
                S[i-mid]='';
                get_extend();
                len=strlen(S);
                len1=strlen(T);
                for(i=0;i<len;i++)
                    if(i+mid+extend[i]==len1)
                    {
                        max=extend[i];
                        break;
                    }
                printf("%s",T);
                if(max==-1)
                    max=0;
                len=strlen(T);
                for(i=max;i<len-max;i++)
                    printf("%c",s1[T[i]-'a']);
                printf("
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    组合和继承
    解决不了问题
    [zz]shared_ptr 在 stl容器中排序的陷阱
    char ** 初始化
    [zz]c++ list sort方法
    [zz]ZeroMQ的学习和研究
    shared_prt自己使用记录
    rapidxml使用笔记
    HDOJ_ACM_I love sneakers!
    HDOJ_ACM_PiggyBank
  • 原文地址:https://www.cnblogs.com/jiangjing/p/3188229.html
Copyright © 2011-2022 走看看