扩展KMP题目

hdu4333

/*

题意:字符串s[0..n-1],每次把最后一个字符放到前面,求形成的字符串比最初串分别小,相同,大于的个数

因为是为了练习扩展KMP所以肯定是扩展KMP,

为了循环方便,在后面复制字符串,求出next[]数组后,

如果next[i]>n那么肯定相等,如果小于就判断s[ next[i] ]和 s[ i+next[i] ]的大小判断



trick:题目求得是形成的不同的字符串的个数,可以知道相等的字符串肯定只有一个,

而从0..n-1,第二个next[i]大于n那么这个i就是该字符串的循环节;

*/

#include<cstdio>

#include<cstring>

#include<cstdlib>

#include<iostream>

#include<cmath>

#include<vector>

#include<algorithm>

using namespace std;

const int N=100000+10;

char s[N*2];

int next[N*2],n;



void getNext(char *s,int next[]){

    int nn=strlen(s);

    next[0]=nn;

    int p=0;

    while (s[p+1] && s[p]==s[p+1]) p++;

    next[1]=p;

    int k=1;

    for (int i=2;i<nn;i++){

        int p=k+next[k]-1, L=next[i-k];

        if (i+L<=p) next[i]=L;

        else{

            int j=p-i+1;

            if (j<0) j=0;

            while (i+j<nn && s[i+j]==s[j]) j++;

            next[i]=j; k=i;

        }

    }



}



void work(){

    int ret1,ret2,ret3;

    ret1=ret2=ret3=0;

    getNext(s,next);

    for (int i=0;i<n;i++){

        if (i!=0 && next[i]>=n) break;

        if (next[i]<n) {

            if (s[ i+next[i] ]<s[ next[i] ]) ret1++;

            else ret3++;

        }else ret2++;

    }

    printf("%d %d %d\n",ret1,ret2,ret3);

}

int main(){

    int T,cas=0;scanf("%d",&T);

    while (T--){

        scanf("%s",s);

        printf("Case %d: ",++cas);

        n=strlen(s);

        for (int i=0;i<n;i++){

            s[n+i]=s[i];

        }s[n+n]='\0';

       // cout<<s<<endl;

        work();

    }

    return 0;

}

 

hdu3613

  1 /*

  2 题意:将一个串分成俩个串,如果是回文串值就是所有字符的值,如果不是值就为0

  3 问你最大的值是多少;

  4 

  5 分析:因为是扩展KMP的题,很容易想到用扩展KMP判读是否是回文串,而且题目的

  6 特点是至少有一端是端点,这很容易想到前缀和后缀,然后思路就出来了;

  7 首先将串s逆转变成s1,求出s的所有后缀与s1的最长公共子串的长度,

  8 这样分割成两段的后面一段,判断该段是否是回文只要判断最长长度是否等于后面一段的 长度就可以了了

  9 前面一段类似,只是要求出s1的所有后缀与s的最长公共子串的长度,判断方法类似

 10 

 11 

 12 */

 13 #include<cstdio>

 14 #include<cstring>

 15 #include<cstdlib>

 16 #include<iostream>

 17 #include<algorithm>

 18 #include<cmath>

 19 #include<vector>

 20 using namespace std;

 21 const int N=500000+10;

 22 char s[N],s1[N];

 23 int v[30];

 24 int ext1[N],ext2[N],next[N];

 25 void getNext(char *s,int next[]){

 26     int nn=strlen(s);

 27     next[0]=nn;

 28     int p=0;

 29     while (s[p+1] && s[p]==s[p+1]) p++;

 30     next[1]=p;

 31     int k=1, L;

 32     for (int i=2;i<nn;i++){

 33         p=k+next[k]-1; L=next[i-k];

 34         if (i+L<=p) next[i]=L;

 35         else {

 36             int j=p-i+1;

 37             if (j<0) j=0;

 38             while (i+j<nn && s[i+j]==s[j]) j++;

 39             next[i]=j; k=i;

 40         }

 41     }

 42 

 43 }

 44 void getExtend(char *s,char *T,int *ext){

 45     getNext(s,next);

 46     int p=0, nn=strlen(s);

 47     while (s[p] && s[p]==T[p]) p++;

 48     ext[0]=p;

 49     int k=0, L;

 50     for (int i=1;i<nn;i++){

 51         p=k+ext[k]-1; L=next[i-k];

 52         if (i+L<=p) ext[i]=L;

 53         else {

 54             int j=p-i+1;

 55             if(j<0) j=0;

 56             while (i+j<nn && s[i+j]==T[j]) j++;

 57             ext[i]=j; k=i;

 58         }

 59     }

 60 }

 61 int val[N];

 62 void work(){

 63     memset(val,0,sizeof(val));

 64     int len=strlen(s);

 65     for (int i=0;i<len;i++) val[i+1]=val[i]+v[s[i]-'a'];

 66 

 67 

 68 

 69     for (int i=len-1;i>=0;i--) s1[len-i-1]=s[i];

 70     s1[len]='\0';

 71    // cout<<s<<endl<<s1<<endl;

 72     getExtend(s1,s,ext1);

 73     getExtend(s,s1,ext2);

 74 

 75     int ret=0;

 76     for (int i=1;i<len;i++){

 77         int l1=i,l2=len-l1;

 78         int tmp=0;

 79         if (ext1[len-i]==l1) tmp+=val[i];

 80         if (ext2[i]==l2) tmp+=val[len]-val[i];

 81         if (tmp>ret) ret=tmp;

 82     }

 83     printf("%d\n",ret);

 84 }

 85 int main(){

 86     int T;scanf("%d",&T);

 87     while (T--){

 88         for (int i=0;i<26;i++) scanf("%d",v+i);

 89         scanf("%s",s);

 90         work();

 91     }

 92     return 0;

 93 }

 94 /*

 95 4

 96 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

 97 aaadbbbd

 98 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

 99 ab

100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

101 aba

102 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

103 aaaaaaaaaaaaaaa

104 

105 */

 

poj1699

  1 /*

  2 题意:给你n个串,求最短的串使得n个串都包含在里面(n<=10)

  3 从n的数据范围就可以看出状态压缩dp

  4 dp[i][j]表示已经包含了"i"个串,且最后一个串是j的最小长度

  5 预处理出s[i]的后缀与s[j]的前缀的最长公共子串

  6 

  7 */

  8 #include<cstdio>

  9 #include<cstring>

 10 #include<iostream>

 11 #include<cmath>

 12 #include<vector>

 13 #include<algorithm>

 14 using namespace std;

 15 const int N=20+10;

 16 char s[N][N];

 17 int n,next[N],mz[N][N],ext[N];

 18 void getNext(char *s,int *next){

 19     int nn=strlen(s);

 20     next[0]=nn;

 21     int p=0;

 22     while (s[p+1] && s[p]==s[p+1]) p++;

 23     next[1]=p;

 24     int k=1, L;

 25     for (int i=2;i<nn;i++){

 26         p=k+next[k]-1; L=next[i-k];

 27         if (i+L<=p) next[i]=L;

 28         else{

 29             int j=p-i+1;

 30             if (j<0) j=0;

 31             while (i+j<nn && s[i+j]==s[j]) j++;

 32             next[i]=j; k=i;

 33         }

 34     }

 35 }

 36 void getExtend(char *s,char *T,int ext[]){

 37     getNext(s,next);

 38     int nn=strlen(s);

 39     int p=0;

 40     while (s[p] && T[p] && s[p]==T[p]) p++;

 41     ext[0]=p;

 42     int k=0,L;

 43     for (int i=1;i<nn;i++){

 44         p=k+ext[k]-1; L=next[i-k];

 45         if (i+L<=p) ext[i]=L;

 46         else {

 47             int j=p-i+1;

 48             if (j<0) j=0;

 49             while (i+j<nn && s[i+j]==T[j]) j++;

 50             ext[i]=j; k=i;

 51         }

 52     }

 53 }

 54 void init(){

 55     memset(mz,0,sizeof(mz));

 56     for (int i=0;i<n;i++){

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

 58             if (i==j) continue;

 59             getExtend(s[i],s[j],ext);

 60             int nn=strlen(s[i]);

 61             for (int k=0;k<nn;k++){

 62                 if (ext[k]==nn-k) {

 63                     mz[i][j]=nn-k; break;

 64                 }

 65             }

 66         }

 67     }

 68     /*for (int i=0;i<n;i++){

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

 70             cout<<mz[i][j]<<" ";

 71         }cout<<endl;

 72     }*/

 73 }

 74 const int NN=1<<10;

 75 int dp[NN][10];

 76 void Min(int &x,int y){

 77     if (x==-1) x=y;

 78     else x=min(x,y);

 79 }

 80 void work(){

 81     memset(dp,-1,sizeof(dp));

 82     for (int i=0;i<n;i++){

 83         dp[1<<i][i]=strlen(s[i]);

 84     }

 85     for (int i=0;i<(1<<n);i++){

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

 87             if (dp[i][j]==-1) continue;

 88             for (int k=0;k<n;k++){

 89                 if ( i&(1<<k) ) continue;

 90                 Min(dp[i^(1<<k)][k],dp[i][j]+strlen(s[k])-mz[j][k]);

 91              }

 92         }

 93     }

 94     int ret=-1;

 95     for (int i=0;i<n;i++){

 96         Min(ret,dp[(1<<n)-1][i]);

 97     }

 98     cout<<ret<<endl;

 99 

100 }

101 int main(){

102     int T;scanf("%d",&T);

103     while (T--){

104         scanf("%d",&n);

105         for (int i=0;i<n;i++) scanf("%s",s[i]);

106         init();

107         work();

108     }

109     return 0;

110 }

 

你可能感兴趣的:(KMP)