扩展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 }

 

posted @ 2013-06-27 00:58  Rabbit_hair  阅读(848)  评论(0编辑  收藏  举报