• 扩展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
    ",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]='';
           // 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]='';
     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
    ",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 }
  • 相关阅读:
    2019年----沉淀的一年
    条目八《永不建立auto_ptr的容器》
    条目七《如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉》
    条目六《当心C++编译器中最烦人的分析机制》
    条目五《尽量使用区间成员函数代替它们的单元素兄弟》
    cpu上下文切换
    条目四《用empty来代替检查size()是否为0》
    条目三《确保容器中的副本对象高效而正确》
    ORB与LBP、HOG
    C++
  • 原文地址:https://www.cnblogs.com/Rlemon/p/3157898.html
Copyright © 2020-2023  润新知