• 第一周 8.30-9.5


    8.30

    HDU 3336 Count the string

    用dp[i]表示以第i个字符结尾的与前缀相同的串数。

    转移:dp[i]=dp[Next[i]]+1。

    答案即为所有dp求和。

     1 # include <iostream>
     2 # include <cstdio>
     3 using namespace std;
     4 int m,Next[200100],dp[200100];
     5 char b[200100];
     6 
     7 void getNext(void)
     8 {        
     9     Next[0]=Next[1]=0;
    10     for(int i=1;i<m;i++)
    11     {
    12         int j=Next[i];
    13         while(j&&b[i]!=b[j]) j=Next[j];
    14         Next[i+1]=b[i]==b[j]?j+1:0;    
    15     }
    16     return;
    17 }
    18 
    19 int main(void)
    20 {
    21     int T; cin>>T;
    22     while(T--)
    23     {
    24         scanf("%d%s",&m,b);
    25         getNext();
    26         int ans=0;
    27         for(int i=1;i<=m;i++)
    28         {
    29             dp[i]=dp[Next[i]]+1;
    30             ans=(ans+dp[i])%10007;
    31         }
    32         printf("%d
    ",ans);
    33     }
    34     return 0;
    35 }
    Aguin

    HDU 4300 Clairewd’s message

    题意:给一个加密用字母映射。和一个串。串=密文+部分明文(部分明文长度可以为0)。还原出最短的完整密文+明文。

    考虑到密文的长度比如大于整个串的一半。可以取串的前半部分(全是密文)作为一个模式串。

    再把原串加密。即由密文+部分明文→二次加密文+部分密文。作为主串。

    KMP预处理后。从主串的后半部分开始匹配。容易发现匹配到的最后一次的重叠部分就是原串的密文部分。

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 using namespace std;
     5 char S[26],R[26];
     6 char str[100100],a[100100],b[50100];
     7 int m,n,Next[50100];
     8 
     9 void getNext(void)
    10 {        
    11     Next[0]=Next[1]=0;
    12     for(int i=1;i<m;i++)
    13     {
    14         int j=Next[i];
    15         while(j&&b[i]!=b[j]) j=Next[j];
    16         Next[i+1]=b[i]==b[j]?j+1:0;    
    17     }
    18     return;
    19 }
    20 
    21 int main(void)
    22 {
    23     int T; cin>>T;
    24     while(T--)
    25     {
    26         scanf("%s%s",S,str);
    27         for(int i=0;i<26;i++) R[S[i]-'a']=i+'a';
    28         strcpy(a,str);
    29         n=strlen(a),m=(n+1)/2;
    30         memcpy(b,a,sizeof(char)*m);
    31         b[m]=0;
    32         for(int i=0;i<n;i++) a[i]=S[a[i]-'a'];
    33         getNext();
    34         int j=0,pos;
    35         for(int i=m;i<n;i++)
    36         {
    37             while(j&&b[j]!=a[i]) j=Next[j];
    38             if(b[j]==a[i]) j++;
    39         }
    40         for(int i=0;i<n-j;i++) putchar(str[i]);
    41         for(int i=0;i<n-j;i++) putchar(R[str[i]-'a']);
    42         puts("");
    43     }
    44     return 0;
    45 }
    Aguin

    还找到一个exkmp的做法。没用过exkmp试下。

    原串作为主串。再把原串反译一遍作为模式串。

    求完extend之后。从中间往后找第一个满足ex[i]=n-1的地方就是原串密文的终点。

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 # include <algorithm>
     5 using namespace std;
     6 char S[26],R[26],a[100100],b[100100];
     7 int Next[100100],ex[100100];
     8 int n,m;
     9 
    10 void getNext(void)
    11 {
    12     int P=1,j; Next[0]=m;
    13     for(int i=Next[1]=0;i<m-1&&b[i]==b[i+1];) Next[1]=++i;
    14     for(int i=2;i<m;i++)
    15     {
    16         if(Next[i-P]+i<Next[P]+P) Next[i]=Next[i-P];
    17         else
    18         {
    19             j=max(Next[P]+P-i,0);
    20             while(i+j<m&&b[j]==b[j+i]) j++;
    21             Next[i]=j; P=i;
    22         }
    23     }
    24     return;    
    25 }
    26 
    27 void exKMP(void)
    28 {
    29     getNext();
    30     int j,P=0;
    31     for(int i=ex[0]=0;i<m&&a[i]==b[i];) ex[0]=++i;
    32     for(int i=1;i<n;i++)
    33     {
    34         if(Next[i-P]+i<ex[P]+P) ex[i]=Next[i-P];
    35         else
    36         {
    37             j=max(ex[P]+P-i,0);
    38             while(i+j<n&&j<m&&a[j+i]==b[j]) j++;
    39             ex[i]=j; P=i;
    40         }
    41     }
    42     return;
    43 }
    44 
    45 int main(void)
    46 {
    47     int T; cin>>T;
    48     while(T--)
    49     {
    50         scanf("%s%s",S,a);
    51         for(int i=0;i<26;i++) R[S[i]-'a']=i+'a';
    52         n=m=strlen(a);
    53         strcpy(b,a);
    54         for(int i=0;i<n;i++) b[i]=R[b[i]-'a'];
    55         exKMP();
    56         int pos=n;
    57         for(int i=(n+1)/2;i<n;i++)
    58             if(ex[i]==n-i) {pos=i;break;}
    59         for(int i=0;i<pos;i++) putchar(a[i]);
    60         for(int i=0;i<pos;i++) putchar(R[a[i]-'a']);
    61         puts("");
    62     }
    63     return 0;
    64 }
    Aguin

    HDU 1238 Substrings

    因为n很小。直接暴力搞。

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 # include <algorithm>
     5 using namespace std;
     6 char str[101][101];
     7 
     8 int main(void)
     9 {
    10     int T; cin>>T;
    11     while(T--)
    12     {
    13         int n,Maxl=100,ok; scanf("%d",&n);
    14         for(int i=1;i<=n;i++)
    15         {
    16             scanf("%s",str[i]+1);
    17             int tem=strlen(str[i]+1);
    18             Maxl=min(Maxl,tem);
    19         }
    20         int len=strlen(str[1]+1);
    21         for(int l=Maxl;l>0;l--)
    22         {
    23             for(int s=1;s+l-1<=len;s++)
    24             {
    25                 char s1[101],s2[101];
    26                 for(int i=0;i<l;i++) s1[i]=s2[l-i-1]=str[1][s+i];
    27                 s1[l]=s2[l]=0;
    28                 ok=1;
    29                 for(int i=2;i<=n;i++)
    30                     if(!strstr(str[i]+1,s1)&&!strstr(str[i]+1,s2))
    31                         {ok=0;break;}
    32                 if(ok) break;
    33             }
    34             if(ok) {printf("%d
    ",l);break;}
    35         }
    36         if(!ok) puts("0");
    37     }
    38     return 0;
    39 }
    Aguin

    HDU 2328 Corporate Identity

    暴力水果?

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 # include <algorithm>
     5 using namespace std;
     6 char str[4001][300];
     7 
     8 int main(void)
     9 {
    10     int n;
    11     while(~scanf("%d",&n)&&n)
    12     {
    13         char ans[300]={0};
    14         int M=300,pos,flag;
    15         for(int i=1;i<=n;i++)
    16         {
    17             scanf("%s",str[i]+1);
    18             int len=strlen(str[i]+1);
    19             if(len<M){M=len;pos=i;}
    20         }
    21         for(int l=M;l>0;l--)
    22         {
    23             flag=0;
    24             for(int s=1;s+l-1<=M;s++)
    25             {
    26                 char s1[300];
    27                 for(int i=0;i<l;i++) s1[i]=str[pos][s+i];
    28                 s1[l]=0;
    29                 int ok=1;
    30                 for(int i=1;i<=n;i++)
    31                 {
    32                     if(i==pos) continue;
    33                     if(!strstr(str[i]+1,s1))
    34                         {ok=0;break;}
    35                 }
    36                 if(ok)
    37                 {
    38                     if(!flag) strcpy(ans,s1);
    39                     else if(strcmp(s1,ans)<0) strcpy(ans,s1);
    40                     flag=1;
    41                 }
    42             }
    43             if(flag) {printf("%s
    ",ans);break;}
    44         }
    45         if(!flag) puts("IDENTITY LOST");
    46     }
    47     return 0;
    48 }
    Aguin

    8.31

    HDU 3374 String Problem

    这个问题可以分解成两个问题。

    1.求循环节。这个用前面的Next性质即可。

    2.求最小(大)表达法。就是从某个字符开始取使得字典序最小(大)。

    学习了一个O(n)的算法。Link

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 using namespace std;
     5 int m,Next[1000100];
     6 char b[1000100];
     7 
     8 void getNext(void)
     9 {        
    10     Next[0]=Next[1]=0;
    11     for(int i=1;i<m;i++)
    12     {
    13         int j=Next[i];
    14         while(j&&b[i]!=b[j]) j=Next[j];
    15         Next[i+1]=b[i]==b[j]?j+1:0;    
    16     }
    17     return;
    18 }
    19 
    20 int get(int op)
    21 {
    22     int i=0,j=1,k=0;
    23     while(i<m&&j<m&&k<m)
    24     {
    25         int t=b[(i+k)%m]-b[(j+k)%m];
    26         if(!t) k++;
    27         else
    28         {
    29             if(op^(t>0)) i=max(i+k+1,j+1);
    30             else j=max(j+k+1,i+1);
    31             k=0;
    32         }
    33     }
    34     return min(i,j);
    35 }
    36 
    37 int main(void)
    38 {
    39     while(~scanf("%s",b))
    40     {
    41         m=strlen(b);
    42         getNext();
    43         int num=m%(m-Next[m])==0?m/(m-Next[m]):1;
    44         printf("%d %d %d %d
    ",get(0)+1,num,get(1)+1,num);
    45     }
    46     return 0;
    47 }
    Aguin

    9.1-9.4

    什么都没干。

    9.5

    HDU 2609 How many

    最小表示法。直接丢set里去重了。

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <string>
     4 # include <cstring>
     5 # include <algorithm>
     6 # include <set>
     7 using namespace std;
     8 string s;
     9 int m;
    10 
    11 int getMin(void)
    12 {
    13     int i=0,j=1,k=0;
    14     while(i<m&&j<m&&k<m)
    15     {
    16         int t=s[(i+k)%m]-s[(j+k)%m];
    17         if(!t) k++;
    18         else
    19         {
    20             if(t>0) i=max(i+k+1,j+1);
    21             else j=max(j+k+1,i+1);
    22             k=0;
    23         }
    24     }
    25     return min(i,j);
    26 }
    27 
    28 int main(void)
    29 {
    30     int n;
    31     while(~scanf("%d",&n))
    32     {
    33         set <string> S;
    34         for(int i=1;i<=n;i++)
    35         {
    36             cin>>s;
    37             m=s.size();
    38             int pos=getMin();
    39             string s1(s.begin()+pos,s.end());
    40             string s2(s.begin(),s.begin()+pos);
    41             s1+=s2;
    42             S.insert(s1);
    43         }
    44         printf("%d
    ",S.size());
    45     }
    46     return 0;
    47 }
    Aguin

    晚上BC待补。

  • 相关阅读:
    装修后才知道的79件事,无数网友砸出来的经验(转)
    FusionCharts参数说明
    学习好文章
    好文
    oracle删除同一张表的重复记录
    2012的到来,2011年总结
    近期计划
    #¥(#)@()¥。。。。。。。
    疯狂的一周
    可怜的鱼儿
  • 原文地址:https://www.cnblogs.com/Aguin/p/4770302.html
Copyright © 2020-2023  润新知