简单算法—字符串处理

1 模式匹配(kmp)

//模式匹配,kmp算法,复杂度O(m+n)

//返回匹配位置,-1表示匹配失败,传入匹配串和模式串和长度

//可更改元素类型,更换匹配函数

#define MAXN 10000

#define _match(a,b) ((a)==(b))

typedef char elem_t;

int pat_match(int ls,elem_t* str,int lp,elem_t* pat){

       int fail[MAXN]={-1},i=0,j;

       for (j=1;j<lp;j++){

              for (i=fail[j-1];i>=0&&!_match(pat[i+1],pat[j]);i=fail[i]);

              fail[j]=(_match(pat[i+1],pat[j])?i+1:-1);

       }

       for (i=j=0;i<ls&&j<lp;i++)

              if (_match(str[i],pat[j]))

                     j++;

              else if (j)

                     j=fail[j-1]+1,i--;

       return j==lp?(i-lp):-1;

}

2 逆序对数

//序列逆序对数,复杂度O(nlogn)

//传入序列长度和内容,返回逆序对数

//可更改元素类型和比较函数

#include <string.h>

#define MAXN 1000000

#define _cp(a,b) ((a)<=(b))

typedef int elem_t;

elem_t _tmp[MAXN];

int inv(int n,elem_t* a){

       int l=n>>1,r=n-l,i,j;

       int ret=(r>1?(inv(l,a)+inv(r,a+l)):0);

       for (i=j=0;i<=l;_tmp[i+j]=a[i],i++)

              for (ret+=j;j<r&&(i==l||!_cp(a[i],a[l+j]));_tmp[i+j]=a[l+j],j++);

       memcpy(a,_tmp,sizeof(elem_t)*n);

       return ret;

}

3字符串最小表示

/*

       求字符串的最小表示

       输入:字符串

       返回:字符串最小表示的首字母位置(0...size-1)

*/

template <class T>

int MinString(vector <T> &str)

{

       int i, j, k;

       vector <T> ss(str.size() << 1);

       for (i = 0; i < str.size(); i ++) ss[i] = ss[i + str.size()] = str[i];

       for (i = k = 0, j = 1; k < str.size() && i < str.size() && j < str.size(); ) {

              for (k = 0; k < str.size() && ss[i + k] == ss[j + k]; k ++);

              if (k < str.size()) {

                     if (ss[i + k] > ss[j + k])

                            i += k + 1;

                     else j += k + 1;

                     if (i == j) j ++;

              }

       }

       return i < j ? i : j;

}

4最长公共单调子序列

// 最长公共递增子序列, 时间复杂度O(n^2 * logn),空间 O(n^2)

/**

 * n为a的大小, m为b的大小

 * 结果在ans中

 * "define _cp(a,b) ((a)<(b))"求解最长严格递增序列

 */

#define MAXN 1000

#define _cp(a,b) ((a)<(b))

typedef int elem_t;

elem_t DP[MAXN][MAXN];

int num[MAXN], p[1<<20];

int LIS(int n, elem_t *a, int m, elem_t *b, elem_t *ans){

    int i, j, l, r, k;

    DP[0][0] = 0;

    num[0] = (b[0] == a[0]);

    for(i = 1; i < m; i++) {

        num[i] = (b[i] == a[0]) || num[i-1];

        DP[i][0] = 0;

    }

    for(i = 1; i < n; i++){

        if(b[0] == a[i] && !num[0]) {

            num[0] = 1;

            DP[0][0] = i<<10;

        }

        for(j = 1; j < m; j++){

            for(k=((l=0)+(r=num[j-1]-1))>>1; l<=r; k=(l+r)>>1)

                if(_cp(a[DP[j-1][k]>>10], a[i]))

                    l=k+1;

                else

                    r=k-1;

            if(l < num[j-1] && i == (DP[j-1][l]>>10) ){

                if(l >= num[j]) DP[j][num[j]++] = DP[j-1][l];

                else DP[j][l] = _cp(a[DP[j][l]>>10],a[i]) ? DP[j][l] : DP[j-1][l];

            }

            if(b[j] == a[i]){

                for(k=((l=0)+(r=num[j]-1))>>1; l<=r; k=(l+r)>>1)

                    if(_cp(a[DP[j][k]>>10], a[i]))

                        l=k+1;

                    else

                        r=k-1;

                DP[j][l] = (i<<10) + j;

                num[j] += (l>=num[j]);

                p[DP[j][l]] = l ? DP[j][l-1] : -1;

            }

        }

    }

    for (k=DP[m-1][i=num[m-1]-1];i>=0;ans[i--]=a[k>>10],k=p[k]);

    return num[m-1];

}

5 最长子序列

//最长单调子序列,复杂度O(nlogn)

//注意最小序列覆盖和最长序列的对应关系,例如

//"define _cp(a,b) ((a)>(b))"求解最长严格递减序列,则

//"define _cp(a,b) (!((a)>(b)))"求解最小严格递减序列覆盖

//可更改元素类型和比较函数

#define MAXN 10000

#define _cp(a,b) ((a)>(b))

typedef int elem_t;

int subseq(int n,elem_t* a){

       int b[MAXN],i,l,r,m,ret=0;

       for (i=0;i<n;b[l]=i++,ret+=(l>ret))

              for (m=((l=1)+(r=ret))>>1;l<=r;m=(l+r)>>1)

                     if (_cp(a[b[m]],a[i]))

                            l=m+1;

                     else

                            r=m-1;

       return ret;

}

int subseq(int n,elem_t* a,elem_t* ans){

       int b[MAXN],p[MAXN],i,l,r,m,ret=0;

       for (i=0;i<n;p[b[l]=i++]=b[l-1],ret+=(l>ret))

              for (m=((l=1)+(r=ret))>>1;l<=r;m=(l+r)>>1)

                     if (_cp(a[b[m]],a[i]))

                            l=m+1;

                     else

                            r=m-1;

       for (m=b[i=ret];i;ans[--i]=a[m],m=p[m]);

       return ret;

}


6 最大子串匹配

//最大子串匹配,复杂度O(mn)

//返回最大匹配值,传入两个串和串的长度,重载返回一个最大匹配

//注意做字符串匹配是串末的'\0'没有置!

//可更改元素类型,更换匹配函数和匹配价值函数

#include <string.h>

#define MAXN 100

#define max(a,b) ((a)>(b)?(a):(b))

#define _match(a,b) ((a)==(b))

#define _value(a,b) 1

typedef char elem_t;

int str_match(int m,elem_t* a,int n,elem_t* b){

       int match[MAXN+1][MAXN+1],i,j;

       memset(match,0,sizeof(match));

       for (i=0;i<m;i++)

              for (j=0;j<n;j++)

                     match[i+1][j+1]=max(max(match[i][j+1],match[i+1][j]),

                                                 (match[i][j]+_value(a[i],b[i]))*_match(a[i],b[j]));

       return match[m][n];

}

int str_match(int m,elem_t* a,int n,elem_t* b,elem_t* ret){

       int match[MAXN+1][MAXN+1],last[MAXN+1][MAXN+1],i,j,t;

       memset(match,0,sizeof(match));

       for (i=0;i<m;i++)

              for (j=0;j<n;j++){

                     match[i+1][j+1]=(match[i][j+1]>match[i+1][j]?match[i][j+1]:match[i+1][j]);

                     last[i+1][j+1]=(match[i][j+1]>match[i+1][j]?3:1);

                     if ((t=(match[i][j]+_value(a[i],b[i]))*_match(a[i],b[j]))>match[i+1][j+1])

                            match[i+1][j+1]=t,last[i+1][j+1]=2;

              }

       for (;match[i][j];i-=(last[t=i][j]>1),j-=(last[t][j]<3))

              ret[match[i][j]-1]=(last[i][j]<3?a[i-1]:b[j-1]);

       return match[m][n];

}


7 最大子段和

//求最大子段和,复杂度O(n)

//传入串长n和内容list[]

//返回最大子段和,重载返回子段位置(maxsum=list[start]+...+list[end])

//可更改元素类型

typedef int elem_t;

elem_t maxsum(int n,elem_t* list){

       elem_t ret,sum=0;

       int i;

       for (ret=list[i=0];i<n;i++)

              sum=(sum>0?sum:0)+list[i],ret=(sum>ret?sum:ret);

       return ret;

}

elem_t maxsum(int n,elem_t* list,int& start,int& end){

       elem_t ret,sum=0;

       int s,i;

       for (ret=list[start=end=s=i=0];i<n;i++,s=(sum>0?s:i))

              if ((sum=(sum>0?sum:0)+list[i])>ret)

                     ret=sum,start=s,end=i;

       return ret;

}


8 最大子阵和

//求最大子阵和,复杂度O(n^3)

//传入阵的大小m,n和内容mat[][]

//返回最大子阵和,重载返回子阵位置(maxsum=list[s1][s2]+...+list[e1][e2])

//可更改元素类型

#define MAXN 100

typedef int elem_t;

elem_t maxsum(int m,int n,elem_t mat[][MAXN]){

       elem_t matsum[MAXN][MAXN+1],ret,sum;

       int i,j,k;

       for (i=0;i<m;i++)

              for (matsum[i][j=0]=0;j<n;j++)

                     matsum[i][j+1]=matsum[i][j]+mat[i][j];

       for (ret=mat[0][j=0];j<n;j++)

              for (k=j;k<n;k++)

                     for (sum=0,i=0;i<m;i++)

                            sum=(sum>0?sum:0)+matsum[i][k+1]-matsum[i][j],ret=(sum>ret?sum:ret);

       return ret;

}

elem_t maxsum(int m,int n,elem_t mat[][MAXN],int& s1,int& s2,int& e1,int& e2){

       elem_t matsum[MAXN][MAXN+1],ret,sum;

       int i,j,k,s;

       for (i=0;i<m;i++)

              for (matsum[i][j=0]=0;j<n;j++)

                     matsum[i][j+1]=matsum[i][j]+mat[i][j];

       for (ret=mat[s1=e1=0][s2=e2=j=0];j<n;j++)

              for (k=j;k<n;k++)

                     for (sum=0,s=i=0;i<m;i++,s=(sum>0?s:i))

                            if ((sum=(sum>0?sum:0)+matsum[i][k+1]-matsum[i][j])>ret)

                                   ret=sum,s1=s,s2=i,e1=j,e2=k;

       return ret;

}

猜你喜欢

转载自blog.csdn.net/wuqiqi1992/article/details/50236593