Manacher模板,kmp,扩展kmp,最小表示法模板

// Manacher算法,很好用。

char
s[2*N]; //储存临时串 int save[2*N];//中间记录 int Manacher(char tmp[]) { int len=strlen(tmp); int cnt=0; for(int i=0;i<len;i++) { s[cnt++]='#'; s[cnt++]=tmp[i]; } s[cnt++]='#'; memset(save,0,sizeof(save)); int a=0,p=0; int mx=1; for(int i=1;i<cnt-1;i++) { if(i>=p) { int num=1; while(i+num<cnt&&i-num>=0&&s[i+num]==s[i-num]) { num++; } p=i+num-1; //能到达的最远位置 a=i; save[i]=num-1; //从这个位置出发最长的回文 if(save[i]==0) continue; if(s[i]=='#') { if(2*((save[i]-1)/2 +1)>mx) mx=2*((save[i]-1)/2+1); } else { if(2*(save[i]/2)+1>mx) mx=2*(save[i]/2)+1; } } else { int j=2*a-i; if( i+save[j] < p) { save[i]=save[j]; if(save[i]==0) continue; if(s[i]=='#') { if(2*((save[i]-1)/2 +1)>mx) mx=2*((save[i]-1)/2+1); } else { if(2*(save[i]/2)+1>mx) mx=2*(save[i]/2)+1; } } else { int k=2*i-p; while(p+1<cnt&&k-1>=0&&s[p+1]==s[k-1]) { p++; k--; } a=i; save[i]=p-i; if(save[i]==0) continue; if(s[i]=='#') { if(2*((save[i]-1)/2 +1)>mx) mx=2*((save[i]-1)/2+1); } else { if(2*(save[i]/2)+1>mx) mx=2*(save[i]/2)+1; } } } } return mx; }

 

kmp,扩展kmp

// 感觉kmp可以理解。 

#define N 100010
int s[N];
int next[N];
int t[N];

int main()
{
    //freopen("//home//chen//Desktop//ACM//in.text","r",stdin);
    //freopen("//home//chen//Desktop//ACM//out.text","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            scanf("%d",s+i);
        for(int i=0;i<m;i++)
            scanf("%d",t+i);
    ///////////////求next
        int j=0;
        next[0]=0;
        for(int i=1;i<m;i++)
        {
            while(j!=0&&t[j]!=t[i]) j=next[j-1]; 
            if(t[j]==t[i]) j++;
            next[i]=j;
        }

    ///////////////////// 

        j=0;
        int ans=-1;
        for(int i=0;i<n;i++)
        {
            while(j!=0&&s[i]!=t[j]) j=next[j-1];
            if(s[i]==t[j]) j++;
            if(j==m)
            {
                ans=i+1-m+1;
                break;
            }
        }

    ///////////////////
        if(ans==-1)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}


// 扩展kmp。
#defien N 100100

int next[N],sum[N];// sum用来记录

void build(char s[])
{
    memset(next,0,sizeof(next));
    int p=0,a=0;
    next[0]=len;
    for(int i=1;i<len;i++)
    {
        if(i+next[i-a]-1<p)
        {
            next[i]=next[i-a];
        }
        else
        {
            int k=p-i;
            while(p+1<len && s[p+1]==s[k+1])
            {
                p++; k++;
            }
            p=max(p,i);
            next[i]=k+1;
            a=i;
        }
    }
}

void extend_kmp(char s[],char t[])//求从s到t上的最大前缀
{
    memset(sum,0,sizeof(sum));
    int p=-1,a=0;
    for(int i=0;i<len;i++)
    {
        if(i+next[i-a]-1<p)
        {
            sum[i]=next[i-a];
        }
        else
        {
            int k=p-i;
            while(p+1<len && s[p+1]==t[k+1])
            {
                p++; k++;
            }
            p=max(p,i);
            sum[i]=k+1;
            a=i;
        }
    }
}

 

最小表示法

int mistr(char s[],int len)  //输入一串字符,返回最小表示法的起始位置
{
    int i=0,j=1,k=0;
    while(i<len&&j<len&&k<len)
    {
        if(s[i+k]==s[j+k])
        {
            k++;
        }
        else
        {
            if(s[i+k] > s[j+k]) i=i+k+1;
            if(s[i+k] < s[j+k]) j=j+k+1;
            k=0;
            if(i==j) j++;
        }
    }
    return min(i,j);
}

 

posted @ 2013-07-30 22:47  chenhuan001  阅读(488)  评论(0编辑  收藏  举报