1. 程式人生 > >HDU5510-Bazinga-kmp或者hash-毒瘤題

HDU5510-Bazinga-kmp或者hash-毒瘤題

(有任何問題歡迎留言或私聊 && 歡迎交流討論哦

目錄

題意:傳送門

 原題目描述在最下面。
 求最大的下標i,滿足存在一個j(ji)且第j個串不是第i個串的子串。

思路:

O(n2)列舉,kmporhash匹配求解。
 有一個小優化就是:如果kj的子串,ji的子串,那麼對於ki就不用跑一次匹配演算法。然後順便記錄一下這個串有沒有不能和它匹配的串,有就標記一下,方便求解答案。
 最後倒著列舉一遍得出答案。

感覺有點sb的就是最壞情況這個剪枝並沒有用處啊???難道不是嗎,該T還得T



kmp:468ms

#include <cstdio>
#include <cstring>
#define mme(a,b) memset((a),(b),sizeof((a)))  
using namespace std;
int n, m;
char ar[505][2010];
int len[505],nex[2010];
inline void get_next(char *t,int lent){
    nex[0] = -1;
    for(int i = 0,k = -1;i < lent;){
        if(k==-1||t[i] == t[k]){
            ++k;++i;
            nex[i]=k;
        }else
k = nex[k]; } } inline bool kmp(char *s,int lens,char *t,int lent){ if(lens<lent)return 0; if(lent==1){ if(s[0]==t[0])return true; return false; } get_next(t,lent); int i = 0, j = 0; while(i < lens&&j<lent) { if(j==-1||s[i] == t[j]){ i++;j++; if
(j==lent){ return 1; } }else j=nex[j]; } return 0; } int vis[505][505],mp[505]; int main(){ int tim,tc=0; scanf("%d",&tim); while(tim--){ scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%s", ar[i]); len[i]=strlen(ar[i]); } mme(vis,0);mme(mp,0); int ans=-1; for(int i=2;i<=n;++i){ for(int j = i-1; j >= 1; --j){ if(len[j]>len[i]){ vis[i][0]=-1; continue; } if(mp[j]){ vis[i][j]=1; mp[j]=i; continue; } if(kmp(ar[i],len[i],ar[j],len[j])){ vis[i][j]=1; mp[j]=i; }else vis[i][0]=-1; } if(ans!=-1)break; } for(int i=n;i>=1;--i){ if(vis[i][0]==-1){ ans=i;break; } } printf("Case #%d: %d\n", ++tc, ans); } return 0; }

hash 312ms

#pragma comment(linker,"/STACK:102400000,102400000")
#include <bits/stdc++.h>
#define mme(a,b) memset((a),(b),sizeof((a)))  
#define fuck(x) cout<<"* "<<x<<"\n"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;
const int N = 1e5 + 7;
const int MX = 2e6 + 7;
const uLL base = 131;
int n, m;
int len[505],vis[505][505],mp[505];
char t[2010];
uLL pw[2007], hs[515][2007];
void get_hash(int k, int lent){
  hs[k][0] = 0;
  for(int i = 1;i <= lent; ++i){
    hs[k][i] = hs[k][i-1]*base + (t[i]-'a');
  }
}
uLL calc(int k, int l, int r){
  return hs[k][r]-hs[k][l-1]*pw[r-l+1];
}
int main(){
  pw[0] = 1;
  for(int i = 1;i <= 2005; ++i){
    pw[i] = pw[i-1]*base;
  }
  int tim,tc = 0;
  scanf("%d", &tim);
  while(tim--){
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i){
      scanf("%s",t+1);
      len[i] = strlen(t+1);
      get_hash(i, len[i]);
    }
    mme(vis,0);mme(mp,0);
    int ans = -1;
    for(int i = 2; i <= n; ++i){
      for(int j = i-1; j >= 1; --j){
        if(len[j] > len[i]){
          vis[i][0]=-1;
          continue;
        }
        if(mp[j])continue;
        int flag=0;
        for(int h = 1; h+len[j]-1 <= len[i]; ++h){
          if(calc(i,h,h+len[j]-1) == hs[j][len[j]]){
            flag=1;
            break;
          }
        }
        if(flag){
          mp[j] = i;
        }else{
          vis[i][0]=-1;
        }
      }
    }
    for(int i=n;i>=1;--i){
      if(vis[i][0]==-1){
        ans=i;
        break;
      }
    }
    printf("Case #%d: %d\n", ++tc, ans);
  }
  return 0;
}

原題目描述:

這裡寫圖片描述