zoukankan      html  css  js  c++  java
  • 【模拟7.25】匹配

    作为考试第一题,难度比较小,开始时忘记KMP打法,于是先做第二题了,迅速水完第二题

    回来想了想,其实单论数据范围hash明显可解甚至更快

    KMP时间复杂度O(n+m)即两个字符串长度

    hash该题中复杂度O(n).........

    没啥可说的

    hash:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<string>
      5 #include<algorithm>
      6 #include<cmath>
      7 #include<stack>
      8 #include<map>
      9 #include<queue>
     10 #define ps push_back
     11 #define MAXN 205101
     12 #define ll unsigned long long
     13 using namespace std;
     14 int T;
     15 ll hash_A,hash_B,hash_AA,hash_BB;
     16 int la,lb;
     17 ll base=131ll;
     18 ll base1=1ll;
     19 char a[MAXN],b[MAXN];
     20 char c;
     21 ll bass,bass1;
     22 int main()
     23 {
     24    scanf("%d",&T);
     25    while(T--)
     26    {
     27        scanf("%d%d",&la,&lb);
     28        if(lb<=10000)
     29        {
     30         scanf("%s",a+1);
     31         base=131;
     32         base1=1;
     33         hash_A=0;hash_B=0;
     34         for(int i=1;i<=lb;++i)
     35         {
     36             b[i]=a[i];
     37         }
     38         cin>>c;
     39         lb++;
     40         b[lb]=c;
     41         int kx=0;
     42         int ans=0;
     43         for(int i=lb;i>=1;--i)
     44         {
     45             kx++;
     46             hash_A=(hash_A*base)+(a[kx]-'a'+1);
     47             hash_B=(b[i]-'a'+1)*base1+hash_B;
     48             base1*=base;  
     49             //printf("i=%d ",i);
     50             //cout<<a[kx]<<b[i]<<endl;
     51             //printf("hase_A=%lld B=%lld
    ",hash_A,hash_B);
     52             if(hash_A==hash_B)
     53             {
     54                 ans=kx;
     55             }
     56         }
     57         printf("%d
    ",ans);
     58         base=131;
     59         base1=1;
     60         hash_A=0;hash_B=0;
     61       }
     62       else
     63       {
     64         scanf("%s",a+1);
     65         base=131;bass=1331;
     66         base1=1;bass1=1;
     67         hash_A=hash_B=hash_AA=hash_BB=0;
     68         for(int i=1;i<=lb;++i)
     69         {
     70             b[i]=a[i];
     71         }
     72         cin>>c;
     73         lb++;
     74         b[lb]=c;
     75         int kx=0;
     76         int ans=0;
     77         for(int i=lb;i>=1;--i)
     78         {
     79              kx++;
     80              hash_A=(hash_A*base)+(a[kx]-'a'+1);
     81              hash_B=(b[i]-'a'+1)*base1+hash_B;
     82             
     83              hash_AA=(hash_AA*bass)+(a[kx]-'a'+1);
     84              hash_BB=(b[i]-'a'+1)*bass1+hash_BB;
     85             
     86              base1*=base; 
     87              bass1*=bass; 
     88             //printf("i=%d ",i);
     89             //cout<<a[kx]<<b[i]<<endl;
     90             //printf("hase_A=%lld B=%lld
    ",hash_AA,hash_BB);
     91              if(hash_A==hash_B&&hash_AA==hash_BB)
     92              {
     93                  ans=kx;
     94              }
     95         }
     96         printf("%d
    ",ans);
     97         base=131;bass=1331;
     98         base1=1;bass1=1;
     99         hash_A=hash_B=hash_AA=hash_BB=0; 
    100       }
    101    }
    102 }
    103 /*
    104 2
    105 5 3
    106 adabc
    107 d
    108 */
    View Code

    (为了防数据卡我,我还打了双hash,好像没啥必要......)

    KMP:

    考后复习了一下

    首先next数组 next[i]表示该字符串以i结尾的最长后缀==前缀的长度

    定义指针j=0从i=2开始移动(由定义可知next[1]=0)

    然后while(j!=0&&a[j+1]!=a[i])j=next[j];

    应用了next数组的性质,若是当前的字符和指针的下一个字符不匹配就向前移动

    (由next数组定义可知,这样移动正确)

    然后求解f数组相似不再细说

    (其实暴力的字符串用hash都能过.......)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<stack>
     8 #include<map>
     9 #include<queue>
    10 #define ps push_back
    11 #define MAXN 205101
    12 #define ll unsigned long long
    13 using namespace std;
    14 int T;
    15 int la,lb;
    16 char a[MAXN],b[MAXN];
    17 int nxt[MAXN],f[MAXN];
    18 char c;
    19 int main()
    20 {
    21    scanf("%d",&T);
    22    while(T--)
    23    {
    24        memset(nxt,0,sizeof(nxt));
    25        memset(f,0,sizeof(f));
    26        scanf("%d%d",&la,&lb);
    27        scanf("%s",a+1);
    28        for(int i=1;i<=lb;++i)
    29        {
    30            b[i]=a[i];
    31        }
    32        cin>>c;
    33        lb++;
    34        b[lb]=c;
    35        nxt[1]=0;
    36        for(int i=2,j=0;i<=la;++i)
    37        {
    38            while(j>0&&a[i]!=a[j+1])j=nxt[j];
    39            if(a[i]==a[j+1])j++;
    40            
    41            nxt[i]=j;
    42        }
    43        for(int i=1,j=0;i<=lb;++i)
    44        {
    45            while(j>0&&(j==la||b[i]!=a[j+1]))
    46            {
    47            //printf("j=%d
    ",j);
    48            j=nxt[j];}
    49            if(b[i]==a[j+1])j++;
    50            
    51            f[i]=j;//printf("i=%d %d
    ",i,f[i]);
    52        }
    53        printf("%d
    ",f[lb]);
    54   }
    55 }
    56 /*
    57 2
    58 5 3
    59 adabc
    60 d
    61 */
    View Code
  • 相关阅读:
    Quartz使用及注意事项
    .Net下性能调优浅析
    .Net下Redis使用注意事项
    WCF服务开发与调用的完整示例
    超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。
    C# DES
    webService访问加密-Soapheader
    WebMethod 属性
    互联网 免费的WebService接口
    利用XPath解析带有xmlns的XML文件
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11248053.html
Copyright © 2011-2022 走看看