zoukankan      html  css  js  c++  java
  • UVA 11475 Extend to Palindrome (kmp || manacher || 后缀数组)

    题目链接:点击打开链接

    题意:给你一个串,让你在串后面添加尽可能少的字符使得这个串变成回文串。

    思路:这题可以kmp,manacher,后缀数组三种方法都可以做,kmp和manacher效率较高,时间复杂度是O(n),后缀数组时间复杂度是O(nlogn).思路是求出元串的后缀和反串的前缀匹配的最大长度。用后缀数组的时候求出l=lcp(i,len+1),判断l+i是不是等于len,如果等于那么就是结果。


    kmp:

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<string>
    #include<bitset>
    #include<algorithm>
    using namespace std;
    #define lson th<<1
    #define rson th<<1|1
    typedef long long ll;
    typedef long double ldb;
    #define inf 99999999
    #define pi acos(-1.0)
    #define maxn 1000600
    char s1[maxn],s2[maxn];
    int nextt[maxn],len;
    int pd(char *s1,char *s2){
        int i,j,len1,len2;
        len1=len2=len;
        i=0;j=-1;
        memset(nextt,-1,sizeof(nextt));
        while(i<len2){
            if(j==-1 || s2[i]==s2[j]){
                i++;
                j++;
                nextt[i]=j;
            }
            else j=nextt[j];
        }
        i=0;j=0;
        int ans=1;
        while(i<len1 && j<len2){
            if(j==-1 || s1[i]==s2[j]){
                //ans=max(ans,j+1);  注意这句不能加,因为要求的是当i=len1时候,串二最大匹配了多少长度
                i++;
                j++;
            }
            else j=nextt[j];   //这里要解释一下,这里的意思是s[i]和s[j]不匹配了,那么看前j个字符前缀和后缀匹配的程度,注意,这里前j个字符是s[0]...s[j-1]
        }
        ans=j;
        return ans;
    }
    
    int main()
    {
        int n,m,i,j,ans;
        while(scanf("%s",s1)!=EOF)
        {
            strcpy(s2,s1);
            len=strlen(s1);
            reverse(s2,s2+len);
            ans=pd(s1,s2);
            printf("%s",s1);
            for(i=len-1-ans;i>=0;i--){
                printf("%c",s1[i]);
            }
            printf("
    ");
        }
        return 0;
    }

    manacher:

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<string>
    #include<bitset>
    #include<algorithm>
    using namespace std;
    #define lson th<<1
    #define rson th<<1|1
    typedef long long ll;
    typedef long double ldb;
    #define inf 99999999
    #define pi acos(-1.0)
    #define maxn 100060
    char s[maxn],ss[maxn*2];  //要开两倍大小
    int p[maxn*2];
    int main()
    {
        int n,m,i,j,mx,idx,maxx,len,len1;
        while(scanf("%s",s)!=EOF)
        {
            len=strlen(s);
            len1=len;
            ss[0]='$';
            ss[1]='#';
            for(i=0;i<len;i++){
                ss[i*2+2]=s[i];
                ss[i*2+3]='#';
            }
            mx=0;maxx=0;
            len=2*len+2;
            int ans=inf;
            for(i=1;i<len;i++){
                if(mx>i){       //这里的mx为满足条件的后一个,这样如果i<=idx+p[i]-1就能比较了
                    p[i]=min(p[idx*2-i],mx-i);
                }
                else p[i]=1;
                while(ss[i+p[i]]==ss[i-p[i]]){
                    p[i]++;
                }
                if(maxx<p[i])maxx=p[i];
                if(mx<i+p[i]){  //这里更新的mx也是范围内的后一个
                    mx=i+p[i];
                    idx=i;
                }
                if(i+p[i]-1==len-1 ){
                    //printf("--->%d
    ",i);
                    ans=min(ans,(i-(p[i]-1)) /2 );
                }
            }
            printf("%s",s);
            for(i=ans-1;i>=0;i--){
                printf("%c",s[i]);
            }
            printf("
    ");
    
            //printf("%d
    ",ans);
        }
        return 0;
    }

    后缀数组:

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<string>
    #include<bitset>
    #include<algorithm>
    using namespace std;
    #define lson th<<1
    #define rson th<<1|1
    typedef long long ll;
    typedef long double ldb;
    #define inf 99999999
    #define pi acos(-1.0)
    #define M 100050
    #define maxn 200050
    char s1[M],s2[M];
    int a[maxn];
    int idx(char c){
        if(c>='a' && c<='z')return c-'a'+1;
        if(c>='A' && c<='Z')return c-'A'+1+26;
    }
    
    int sa[maxn];
    int wa[maxn],wb[maxn],wv[maxn],we[maxn];
    int rk[maxn],height[maxn];
    int cmp(int *r,int a,int b,int l){
        return r[a]==r[b]&&r[a+l]==r[b+l];
    }
    void build_sa(int *r,int n,int m)
    {
        int i,j,p,*x=wa,*y=wb,*t;
        for(i=0;i<m;i++)we[i]=0;
        for(i=0;i<n;i++)we[x[i]=r[i]]++;
        for(i=1;i<m;i++)we[i]+=we[i-1];
        for(i=n-1;i>=0;i--)sa[--we[x[i]]]=i;
        for(j=1,p=1;p<n;j*=2,m=p){
            for(p=0,i=n-j;i<n;i++)y[p++]=i;
            for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
            for(i=0;i<n;i++)wv[i]=x[y[i]];
            for(i=0;i<m;i++)we[i]=0;
            for(i=0;i<n;i++)we[wv[i]]++;
            for(i=1;i<m;i++)we[i]+=we[i-1];
            for(i=n-1;i>=0;i--)sa[--we[wv[i]]]=y[i];
            for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        }
    }
    
    void calheight(int *r,int n)
    {
        int i,j,k=0;
        for(i=1;i<=n;i++)rk[sa[i]]=i;
        for(i=0;i<n;height[rk[i++] ]=k){
            for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
        }
    }
    
    int minx[200100][30];
    void init_rmq(int n)
    {
        int i,j;
        for(i=1;i<=n;i++)minx[i][0]=height[i];
        for(j=1;j<=20;j++){
            for(i=1;i<=n;i++){
                if(i+(1<<j)-1<=n)
                {
                    minx[i][j]=min(minx[i][j-1],minx[i+(1<<(j-1))][j-1]);
                }
            }
        }
    }
    
    
    int lcp(int l,int r)
    {
        int k,i;
        l=rk[l];r=rk[r];
        if(l>r)swap(l,r);
        l++;
        k=(log((r-l+1)*1.0)/log(2.0));
        return min(minx[l][k],minx[r-(1<<k)+1][k]);
    }
    
    
    int main()
    {
        int n,m,i,j,len,l;
        while(scanf("%s",s1)!=EOF)
        {
            strcpy(s2,s1);
            len=strlen(s1);
            reverse(s2,s2+len);
            n=0;
            for(i=0;i<len;i++){
                a[n++]=idx(s1[i]);
            }
            a[n++]=55;
            for(i=0;i<len;i++){
                a[n++]=idx(s2[i]);
            }
            a[n]=0;
    
            build_sa(a,n+1,60);
            calheight(a,n);
            init_rmq(n);
    
            for(i=0;i<len;i++){
                l=lcp(i,len+1);
                if(i+l==len)break;
            }
            printf("%s",s1);
            for(i=len-1-l;i>=0;i--){
                printf("%c",s1[i]);
            }
            printf("
    ");
        }
        return 0;
    }


  • 相关阅读:
    设计模式之访问者模式
    设计模式之命令模式
    设计模式之迭代器模式
    tomcat8.0.11性能优化
    java 基础 --集合--012
    StringBuffer和StringBuilder的区别
    jquery 入门
    java 基础 --匿名内部类-008
    java 基础 --多态--009
    java 基础--继承--007
  • 原文地址:https://www.cnblogs.com/herumw/p/9464488.html
Copyright © 2011-2022 走看看